共享内存是所有IPC通信中效率最高的,它通过把文件映射到用户进程空间,然后直接通过地址访问来实现多进程通信。相对于其他IPC通信方式而言,少去了把数据从用户空间复制到内核空间,再从内核空间复制到用户空间的过程,因此效率相当高。
用图形来表示就是:
操作共享内存的函数:
1 2 |
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t len); |
第一个是映射共享内存的函数,参数说明:
addr
: 需要映射的共享内存起始地址,一般来说传入NULL。len
: 映射出来的共享内存块大小。prot
: 内存权限,长用的权限是PROT_READ | PROT_WRITE
,表示可读可写。flags
: 共享内存区域的属性,可以设置为MAP_SHARED
或者MAP_PRIVATE
,如果是前者,当前进程对共享内存区域的修改对其他进程可见,否则就不可见。fd
: 共享内存文件的文件描述符。offset
: 文件的偏移,从文件的offset处开始共享内存。
使用示例
以下代码展示了一个共享内存的操作示例,通过共享内存在父子进程间共享一个int类型的变量,然后父进程修改值,子进程读:
代码中忽略掉了一些不相关的错误处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/mman.h> #include <semaphore.h> int main() { int fd, n = 12345; int *ptr; sem_t *sem; pid_t pid; // 创建信号 sem = sem_open("my_sem", O_RDWR | O_CREAT, 0755, 0); sem_unlink("my_sem"); // 往文件写一个数据 fd = open("mmapfile", O_RDWR | O_CREAT, 0755); write(fd, (void *)&n, sizeof(int)); // 创建共享内存 ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); pid = fork(); if (pid == 0) { // 子进程,等待父进程修改完共享内存后打印出来 sem_wait(sem); printf("child:\t%d\n", *ptr); } else if (pid > 0) { // 父进程,把共享内存加一 printf("parent:\t%d\n", *ptr); (*ptr)++; sem_post(sem); } else { perror("fork error"); } // 关闭信号量 sem_close(sem); // 取消映射共享内存 munmap(ptr, sizeof(int)); // 删掉共享内存文件 unlink("mmapfile"); return 0; } |
代码中信号量的作用是确保子进程在父进程执行完成后才执行,父进程先把共享内存的数据加1,然后子进程读取共享内存的数据应该要变成12346。
执行结果符合预期:
评论