上一篇進程間通訊:共享內存沒有實現互斥鎖保護,今天用信號量實現一個進程間互斥鎖,保護共享變量的修改。html
參考資料:linux
http://man7.org/linux/man-pages/man7/sem_overview.7.htmlcentos
http://man7.org/linux/man-pages/man3/sem_init.3.htmlpost
http://man7.org/linux/man-pages/man3/sem_post.3.htmlcentos7
http://man7.org/linux/man-pages/man3/sem_wait.3.htmlspa
http://man7.org/linux/man-pages/man3/sem_destroy.3.htmlcode
實現思路:父進程開闢一段共享內存,將開始sizeof(sem_t)大小做爲互斥鎖存儲空間,在父進程中映射這一段內存,在以後fork的子進程將會繼承這一映射關係,進而實現進程間共享互斥鎖。htm
代碼實現:blog
#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <semaphore.h> #define MAPPING_SIZE 4096 int main (int argc,char* argv[]){ int mapfd; const char* mapname = "/number"; // 開闢一段共享內存 mapfd = shm_open(mapname,O_RDWR|O_CREAT,S_IRUSR | S_IWUSR); if(mapfd == -1){ perror("shm_open fail"); exit(EXIT_FAILURE); } // ftruncate能夠用來設置共享內存到指定大小 if(ftruncate(mapfd,MAPPING_SIZE) == -1){ perror("ftruncate fail"); close(mapfd); exit(EXIT_FAILURE); } // 將共享內存開始處做爲進程間互斥鎖 void* sp = mmap(NULL,MAPPING_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,mapfd,0); if(sp == NULL){ perror("mmap fail"); close(mapfd); exit(EXIT_FAILURE); } sem_t* mutex = (sem_t*)sp; if(sem_init(mutex,1,1) != 0) { perror("sem_init fail"); close(mapfd); exit(EXIT_FAILURE); } int * num = (int*)(sp+sizeof(sem_t)); int stat,cid,n,procCount=0,maxProcCount=8; for(n = 0;n<maxProcCount;++n){ cid = fork(); if (cid == -1){ perror("fork fail"); continue; } if(cid == 0){ sem_wait(mutex); (*num)++; sem_post(mutex); printf("Process %d: %d\n",getpid(),*num); if(munmap(sp,MAPPING_SIZE) == -1){ perror("munmap fail"); } close(mapfd); _exit(EXIT_SUCCESS); } ++procCount; } while(procCount--){ cid = wait(&stat); if(cid == -1){ perror("wait fail"); break; } printf("%d cid %d exit.\n",procCount,cid); } sem_destroy(mutex); close(mapfd); // 若是不執行shm_unlink則屢次執行程序的輸出是遞增的,共享內存被重複利用了 shm_unlink(mapname); }
運行效果:繼承
[root@centos7 c]# gcc -lrt -pthread process.c -o process [root@centos7 c]# ./process Process 11086: 1 Process 11087: 2 Process 11088: 3 Process 11089: 4 Process 11090: 5 Process 11092: 6 7 cid 11086 exit. 6 cid 11087 exit. 5 cid 11088 exit. 4 cid 11089 exit. 3 cid 11090 exit. 2 cid 11092 exit. Process 11093: 7 Process 11091: 8 1 cid 11093 exit. 0 cid 11091 exit.