进程间通信:共享内存+互斥锁

上一篇进程间通信:共享内存没有实现互斥锁保护,今天用信号量实现一个进程间互斥锁,保护共享变量的修改。

参考资料:

http://man7.org/linux/man-pages/man7/sem_overview.7.html

http://man7.org/linux/man-pages/man3/sem_init.3.html

http://man7.org/linux/man-pages/man3/sem_post.3.html

http://man7.org/linux/man-pages/man3/sem_wait.3.html

http://man7.org/linux/man-pages/man3/sem_destroy.3.html

实现思路:父进程开辟一段共享内存,将开始sizeof(sem_t)大小作为互斥锁存储空间,在父进程中映射这一段内存,在之后fork的子进程将会继承这一映射关系,进而实现进程间共享互斥锁。

代码实现:

#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.

猜你喜欢

转载自www.cnblogs.com/ling-diary/p/10538275.html
今日推荐