使用mmap和posix semaphores做进程间通信与同步
来源:互联网 发布:php 打开文件 编辑:程序博客网 时间:2024/06/16 10:13
为什么要使用mmap进行IPC呢,个人总结有三点:
- 接口简单好用
- 多进程操作同一文件的时候使用mmap维护一下读写信息的meta数据非常方便
- 方便在非亲属进程间同步时使用
为什么要用posix semaphore进程同步呢,个人总结有三点:
- 接口简单好用
- 效率高,在Linux3.2.0开销只有0.41个Clock(而XSI semaphore有7.33)
- 方便在非亲属进程间同步时使用
posix semaphore有两种使用方式,一种是named semaphore另一种就是unnamed semaphore,它们创建与销毁接口不一样,关于posix semaphore的接口可以参考APUE,然后这里和这里都非常详细介绍了命名posix semaphore和内存中非命名posix semaphore的使用方法。
named semaphore使用的时候需要相关进程都使用同一名字,那各个毫无亲戚关系的进程这么知道使用改名字打了哪个信号量文件呢?在/dev/shm中会存放一个sem file,比如如果使用"mutex"作为semaphore名字的时候,在/dev/shm会创建一个sem.mutex的文件,其它进程在使用"mutex"这个名字打开semaphore的时候会使用该文件,这样各个进程就知道了是同一semaphore了,代码中有注释。
unnamed semaphore则可以通过类似于共享内存的方式存放semaphore变量(sem_t),这里我们本身维护了一个meta被mmap了被进程共享,那可以把这个变量放在meta的数据结构中(封装),这样既可以IPC也可以同步了。
下面两段代码第一段是named semaphore & mmap,第二段是unamed semaphore & mmap,为了简化就是两个进程读写一个cnt,posix semaphore需要加-lpthread。
-----------------------------------------named semaphore-----------------------------------------------
#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <semaphore.h>#include <fcntl.h>#include <sys/mman.h>typedef struct _meta_t { int _cnt;} meta_t;int main(){ // create a semaphore file named sem.mutex in /dev/shm // use 0-1 name semaphore so set the value as 1 sem_t* mutex = sem_open("mutex", O_CREAT, 0664, 1); if (!mutex) { perror("open mutex failed"); abort(); } // create a file at first before create a named mmap FILE* f = fopen("./log.meta","w+"); if (!f) { fprintf(stderr,"file open failed\n"); abort(); } // "If don't set the output file's size the call mmap for the output is // successful but the first reference to the associated memeory region // generates a SIGBUS signal" --- APUE c14.8 p530 ftruncate(fileno(f), sizeof(meta_t)); meta_t* ptr = mmap(NULL,sizeof(meta_t), PROT_WRITE, MAP_SHARED, fileno(f), 0); if (ptr == MAP_FAILED) { fprintf(stderr,"mmap failed\n"); fclose(f); abort(); } ptr->_cnt = 0; int cnt = 10; while (cnt--) { sem_wait(mutex); printf("a : %d\n", ptr->_cnt); ++ptr->_cnt; printf("a : %d\n", ptr->_cnt); sem_post(mutex); sleep(1); } sem_close(mutex); sem_unlink("mutex"); munmap(f,sizeof(meta_t)); close(f); return 0;}/////////////////////////////////////////////#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <semaphore.h>#include <fcntl.h>#include <sys/mman.h>typedef struct _meta_t { int _cnt;} meta_t;int main(){ // create a semaphore file named sem.mutex in /dev/shm // use 0-1 name semaphore so set the value as 1 sem_t* mutex = sem_open("mutex", O_CREAT, 0664, 1); if (!mutex) { perror("open mutex failed"); abort(); } // create a file at first before create a named mmap FILE* f = fopen("./log.meta","a+"); if (!f) { fprintf(stderr,"file open failed\n"); abort(); } // "If don't set the output file's size the call mmap for the output is // successful but the first reference to the associated memeory region // generates a SIGBUS signal" --- APUE c14.8 p530 // ftruncate(fileno(f), sizeof(meta_t)); no need in this process meta_t* ptr = mmap(NULL,sizeof(meta_t), PROT_WRITE, MAP_SHARED, fileno(f), 0); if (ptr == MAP_FAILED) { fprintf(stderr,"mmap failed\n"); fclose(f); abort(); } int cnt = 10; while (cnt--) { sem_wait(mutex); printf("b : %d\n", ptr->_cnt); --ptr->_cnt; printf("b : %d\n", ptr->_cnt); sem_post(mutex); sleep(1); } sem_close(mutex); sem_unlink("mutex"); munmap(f,sizeof(meta_t)); close(f); return 0;}
-------------------------------unnamed semaphore------------------------------------------
#include<stdio.h>#include<semaphore.h>#include<fcntl.h>#include<sys/mman.h>typedef struct _meta_t { int _cnt; sem_t _mutex;} meta_t, *ptr_meta_t;int main(){ FILE* f = fopen("./log.meta","w+"); if (!f) { fprintf(stderr,"file open failed\n"); } // If don't set the output file's size the call mmap for the output is // successful but the first reference to the associated memeory region // generates a SIGBUS signal ftruncate(fileno(f), sizeof(meta_t)); meta_t* ptr = mmap(NULL,sizeof(meta_t), PROT_WRITE, MAP_SHARED, fileno(f), 0); if (ptr == MAP_FAILED) { fprintf(stderr,"mmap failed\n"); return -1; } ptr->_cnt = 0; int ret = sem_init(&ptr->_mutex, 1, 1); if (ret) { fprintf(stderr,"init semaphore failed\n"); } int cnt = 10; while (cnt--) { sem_wait(&ptr->_mutex); printf("c : %d\n", ptr->_cnt); (ptr->_cnt) += 1; printf("c : %d\n", ptr->_cnt); sem_post(&ptr->_mutex); sleep(1); } sem_destroy(&ptr->_mutex); munmap(f,sizeof(meta_t)); close(f); return 0;}/////////////////////////////////////////////////////#include<stdio.h>#include<semaphore.h>#include<fcntl.h>#include<sys/mman.h>typedef struct _meta_t { int _cnt; sem_t _mutex;} meta_t, *ptr_meta_t;int main(){ FILE* f = fopen("./log.meta","r+"); // do not use w+ in this process if (!f) { fprintf(stderr,"file open failed\n"); } // If don't set the output file's size the call mmap for the output is // successful but the first reference to the associated memeory region // generates a SIGBUS signal // ftruncate(fileno(f), sizeof(meta_t)) no need in this process meta_t* ptr = mmap(NULL,sizeof(meta_t), PROT_WRITE, MAP_SHARED, fileno(f), 0); if (ptr == MAP_FAILED) { fprintf(stderr,"mmap failed\n"); return -1; } int ret = sem_init(&ptr->_mutex, 1, 1); if (ret) { fprintf(stderr,"init semaphore failed\n"); } int cnt = 10; while (cnt--) { sem_wait(&ptr->_mutex); printf("d : %d\n", ptr->_cnt); (ptr->_cnt) -= 1; printf("d : %d\n", ptr->_cnt); sem_post(&ptr->_mutex); sleep(1); } sem_destroy(&ptr->_mutex); munmap(f,sizeof(meta_t)); close(f); return 0;}
- 使用mmap和posix semaphores做进程间通信与同步
- 使用mmap实现进程间通信
- Linux 进程间通信 - 信号灯(Semaphores)
- 进程间通信-mmap
- 进程间通信和同步
- Linux进程间通信 -- mmap函数的使用
- Linux下多任务间通信和同步-POSIX信号量
- 线程同步与进程间通信的方式和机制
- 多线程 : 使用 wait 和 notify 实现进程间同步通信
- 进程同步与通信
- linux进程通信:使用posix消息队列mq进行线程或进程间的通信
- Linux进程间通信与同步
- Linux进程间同步与通信
- 进程间通信之mmap共享内存
- linux系统编程:进程间通信-mmap
- 进程间通信(七)mmap
- linux 进程间通信之mmap
- Linux--mmap实现进程间通信
- 自己动手做J浏览器——基于JAVA和火狐内核(gecko)
- 为什么选择这种技术而不选择另一种技术?
- 第十三次codeforces竞技结束 #265 Div 2
- myeclipse自动生成hibernate的Mapping和po文件
- poj1979
- 使用mmap和posix semaphores做进程间通信与同步
- CPP -- W3 类和对象进阶
- Block块笔记
- Java笔试题集锦
- 网页结构基础1
- JAVA 基础(一)
- IT忍者神龟之Database Link详解
- 自己的stackoverflow的账号信息
- C++ 文件输入输出问题