進程是一個獨立的資源管理單元,不一樣進程間的資源是獨立的,不能在一個進程中訪問另外一個進程的用戶空間和內存空間。可是,進程不是孤立的,不一樣進程之間須要信息的交互和狀態的傳遞,所以須要進程間數據的傳遞、同步和異步的機制。linux
固然,這些機制不能由哪個進程進行直接管理,只能由操做系統來完成其管理和維護,Linux提供了大量的進程間通訊機制,包括同一個主機下的不一樣進程和網絡主機間的進程通訊,以下圖所示:
網絡
同主機間的信息交互:數據結構
- 無名管道:
特色:多用於親緣關係進程間通訊,方向爲單向;爲阻塞讀寫;通訊進程雙方退出後自動消失
問題:多進程用同一管道通訊容易形成交叉讀寫的問題- 有名管道:
FIFO(First In First Out),方向爲單向(雙向需兩個FIFO),以磁盤文件的方式存在;通訊雙方一方不存在則阻塞
- 消息隊列:
可用於同主機任意多進程的通訊,但其可存放的數據有限,應用於少許的數據傳遞- 共享內存:
可實現同主機任意進程間大量數據的通訊,但多進程對共享內存的訪問存在着競爭- 同主機進程間同步機制:信號量(Semaphore)
- 同主機進程間異步機制:信號(Signal)
網絡主機間數據交互:Socket(套接字)異步
共享內存,主要是實現進程間大量數據的傳輸。所謂共享內存,即在內存中開闢一段特殊的內存空間,多個進程可互斥訪問,該內存空間具備自身特有的數據結構。
共享內存的數據結構以下 - struct shmid_ds:函數
/* Come from /usr/include/linux/shm.h */ /* Obsolete, used only for backwards compatibility and libc5 compiles */ struct shmid_ds { struct ipc_perm shm_perm; /* operation perms */ int shm_segsz; /* size of segment (bytes) */ __kernel_time_t shm_atime; /* last attach time */ __kernel_time_t shm_dtime; /* last detach time */ __kernel_time_t shm_ctime; /* last change time */ __kernel_ipc_pid_t shm_cpid; /* pid of creator */ __kernel_ipc_pid_t shm_lpid; /* pid of last operator */ unsigned short shm_nattch; /* no. of current attaches */ unsigned short shm_unused; /* compatibility */ void *shm_unused2; /* ditto - used by DIPC */ void *shm_unused3; /* unused */ };
多個進程在使用此共享內存空間時候,必須在進程地址空間與共享內存地址空間之間創建鏈接,即將共享內存空間掛載到進程中;
共享內存是由一個進程開闢,其它任何進程均可以掛載;
共享內存並不會隨着進程的退出而消失,所以最後不使用此內存空間時,必需要手動刪除。this
- 做用:
建立一個共享內存空間
頭文件:操作系統
#include <sys/shm.h>函數原型:3d
int shmget(key_t key, size_t size, int shmflg)參數:code
- key:
ftok()
的返回值
- size: 想要建立的共享內存的大小 (字節)
- shmflg: 共享內存段的建立標識
Macro No. Description Head File IPC_CREAT 01000 若key內存段不存在,則建立;不然返回內存首地址 /usr/include/linux/ipc.h IPC_EXCL 02000 若key內存段存在,則返回錯誤 IPC_NOWAIT 04000 不等待直接返回 shm_r 0400 可讀 /usr/include/linux/shm.h shm_w 0200 可寫 /usr/include/linux/shm.h 返回值:
成功:共享內存空間的標誌 shm_id
失敗:-1blog
- 做用:
對共享內存進程操做,包括:讀取/設置狀態,刪除操做
頭文件:
#include<sys/shm.h>函數原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf)參數:
- shmid :
shmget()
返回值
- buf:臨時共享內存變量信息
- cmd :
Macro No. Description Return IPC_RMID 0 刪除 0 IPC_SET 1 設置 ipc_perm 參數 0 IPC_STAT 2 獲取 ipc_perm 參數 IPC_INFO 3 若 ipcs
命令SHM_LOCK 11 鎖定共享內存段 0 SHM_UNLOCK 12 解鎖共享內存段 0 返回值:
成功:
失敗:-1
- 做用:
將共享內存空間掛載到進程中
頭文件:
#include <sys/shm.h>函數原型:
void *shmat(int shmid, const void *shmaddr, int shmflg)參數:
- shmid :
shmget()
返回值
- shmaddr: 共享內存的映射地址,通常爲0(由系統自動分配地址)
- shmflg : 訪問權限和映射條件
Macro No. Descripton Remind - 0 默認有讀寫權限 經常使用 SHM_RDONLY 010000 只讀 SHM_RDN 020000 Round attach address to SHMLBA boundary SHM_REMAP 040000 take-over region on attach 返回值:
成功:共享內存段首地址
失敗:NULL / (void *)-1
- 做用:
將進程與共享內存空間分離 (只是與共享內存再也不有聯繫,並無刪除共享內存)頭文件:
#include <sys/shm.h>函數原型:
int shmdt(const void *shmaddr)參數:
shmaddr:共享內存的首地址
返回值:
成功: 0
失敗: -1
兩個進程經過共享內存傳輸數據,因共享內存不可同時讀寫,所以採用二元信號量進行進程互斥,具體操做以下:
- init: 設置信號量爲0,此時只容許寫入,不容許讀取(由於共享內存沒有數據);
- Sender: 在sem=0時,寫入數據到共享內存(阻塞讀);寫入完成後,sem=1,此時能夠讀取,不能夠寫入;
- Receiver: 在sem=1時,讀取數據;讀取完成後,sem=0,此時只容許寫入。
1- Sender.c
/* * Filename: Sender.c * Description: */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/sem.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> int main(int argc, char *argv[]) { key_t key; int shm_id; int sem_id; int value = 0; //1.Product the key key = ftok(".", 0xFF); //2. Creat semaphore for visit the shared memory sem_id = semget(key, 1, IPC_CREAT|0644); if(-1 == sem_id) { perror("semget"); exit(EXIT_FAILURE); } //3. init the semaphore, sem=0 if(-1 == (semctl(sem_id, 0, SETVAL, value))) { perror("semctl"); exit(EXIT_FAILURE); } //4. Creat the shared memory(1K bytes) shm_id = shmget(key, 1024, IPC_CREAT|0644); if(-1 == shm_id) { perror("shmget"); exit(EXIT_FAILURE); } //5. attach the shm_id to this process char *shm_ptr; shm_ptr = shmat(shm_id, NULL, 0); if(NULL == shm_ptr) { perror("shmat"); exit(EXIT_FAILURE); } //6. Operation procedure struct sembuf sem_b; sem_b.sem_num = 0; //first sem(index=0) sem_b.sem_flg = SEM_UNDO; sem_b.sem_op = 1; //Increase 1,make sem=1 while(1) { if(0 == (value = semctl(sem_id, 0, GETVAL))) { printf("\nNow, snd message process running:\n"); printf("\tInput the snd message: "); scanf("%s", shm_ptr); if(-1 == semop(sem_id, &sem_b, 1)) { perror("semop"); exit(EXIT_FAILURE); } } //if enter "end", then end the process if(0 == (strcmp(shm_ptr ,"end"))) { printf("\nExit sender process now!\n"); break; } } shmdt(shm_ptr); return 0; }
2- Receiver.c
/* * Filename: Receiver.c * Description: */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/sem.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> int main(int argc, char *argv[]) { key_t key; int shm_id; int sem_id; int value = 0; //1.Product the key key = ftok(".", 0xFF); //2. Creat semaphore for visit the shared memory sem_id = semget(key, 1, IPC_CREAT|0644); if(-1 == sem_id) { perror("semget"); exit(EXIT_FAILURE); } //3. init the semaphore, sem=0 if(-1 == (semctl(sem_id, 0, SETVAL, value))) { perror("semctl"); exit(EXIT_FAILURE); } //4. Creat the shared memory(1K bytes) shm_id = shmget(key, 1024, IPC_CREAT|0644); if(-1 == shm_id) { perror("shmget"); exit(EXIT_FAILURE); } //5. attach the shm_id to this process char *shm_ptr; shm_ptr = shmat(shm_id, NULL, 0); if(NULL == shm_ptr) { perror("shmat"); exit(EXIT_FAILURE); } //6. Operation procedure struct sembuf sem_b; sem_b.sem_num = 0; //first sem(index=0) sem_b.sem_flg = SEM_UNDO; sem_b.sem_op = -1; //Increase 1,make sem=1 while(1) { if(1 == (value = semctl(sem_id, 0, GETVAL))) { printf("\nNow, receive message process running:\n"); printf("\tThe message is : %s\n", shm_ptr); if(-1 == semop(sem_id, &sem_b, 1)) { perror("semop"); exit(EXIT_FAILURE); } } //if enter "end", then end the process if(0 == (strcmp(shm_ptr ,"end"))) { printf("\nExit the receiver process now!\n"); break; } } shmdt(shm_ptr); //7. delete the shared memory if(-1 == shmctl(shm_id, IPC_RMID, NULL)) { perror("shmctl"); exit(EXIT_FAILURE); } //8. delete the semaphore if(-1 == semctl(sem_id, 0, IPC_RMID)) { perror("semctl"); exit(EXIT_FAILURE); } return 0; }