父子等有血缘关系的进程之间也可以通过mmap建立的映射区来完成数据通信。但相应的要在创建映射区的时候指定对应的标志位参数flags:MAP_PRIVATE:(私有映射)父子进程各自独占映射区;MAP_SHARED:(共享映射)父子进程共享映射区。
//父进程创建映射区,然后fork子进程,子进程修改映射区内容,而后,父进程读取映射区内容,查验是否共享。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
int var = 100; //全局变量
int main(void)
{
int *p;
pid_t pid;
int fd;
fd = open("temp", O_RDWR|O_CREAT|O_TRUNC, 0644);
if(fd < 0){
perror("open error");
exit(1);
}
unlink("temp"); //删除临时文件目录项,使之具备被释放条件,该文件没有存在的必要,仅用于完成映射区,来用于父子进程间通信,因此unlink。
ftruncate(fd, 4);
//p = (int *)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
p = (int *)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if(p == MAP_FAILED) {
perror("mmap error");
exit(1);
}
close(fd); //映射区建立完毕,即可关闭文件
pid = fork(); //创建子进程
if(pid == 0){
*p = 2000;
var = 1000;
printf("child, *p = %d, var = %d\n", *p, var);
} else {
sleep(1);
printf("parent, *p = %d, var = %d\n", *p, var);
wait(NULL);
int ret = munmap(p, 4); //释放映射区
if (ret == -1) {
perror("munmap error");
exit(1);
}
}
return 0;
}
[root@localhost mmap]# ./fork_mmap //参数指定为MAP_PRIVATE,能通信
child, *p = 2000, var = 1000
parent, *p = 0, var = 100 //0是随机值,对于没有初始化的指针,其指向的内容是不确定的
[root@localhost mmap]# ./fork_mmap //参数指定为MAP_SHARED,不能通信
child, *p = 2000, var = 1000
parent, *p =2000, var = 100
结论:父子进程共享:1. 打开的文件;2. mmap建立的映射区(但必须要使用MAP_SHARED)。