zoukankan      html  css  js  c++  java
  • 进程间通信:共享内存+互斥锁

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

    参考资料:

    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
    ",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.
    ",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.
  • 相关阅读:
    Java中的多线程
    Service组件
    Notification和Notification Manager的使用
    Java网络编程
    Intent组件
    Android 多任务多线程断点下载
    hdu 2045
    hdu 2492
    poj 2785
    湖南省第六届程序设计大赛D(台球碰撞)
  • 原文地址:https://www.cnblogs.com/ling-diary/p/10538275.html
Copyright © 2011-2022 走看看