進程間通訊:共享內存+互斥鎖

上一篇進程間通訊:共享內存沒有實現互斥鎖保護,今天用信號量實現一個進程間互斥鎖,保護共享變量的修改。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.
相關文章
相關標籤/搜索