实质上mmap是内核借助文件帮我们创建了一个映射区,多个进程之间利用该映射区完成数据传递,由于内核空间多进程共享,因此无血缘关系的进程之间,也可以使用mmap来进行通信,只要设置相应的标记位flag即可。标记位使用MAP_SHARED.
实例代码:
写入进程代码:
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<string.h>
struct STU{
int id;
char name[20];
char sex;
};
void sys_err(char *str){
perror(str);
exit(1);
}
int main(int argc, char *argv[]){
int fd;
struct STU student = {10, "xiaoming", 'm'};
char *mm;
if(argc < 2) {
printf("./a.out file_shared\n");
exit(1);
}
fd = open(argv[1], O_RDWR | O_CREAT, 0664);//打开或创建文件
ftruncate(fd,sizeof(student)); //将fd指定为student大小的文件长度
mm =(char*)mmap(NULL, sizeof(student),PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);//创建映射区
if(mm == MAP_FAILED)
sys_err("mmap error");
close(fd);//关闭文件
while(1){
memcpy(mm, &student, sizeof(student));//往映射区写入数据
student.id++;
sleep(1);
}
munmap(mm, sizeof(student));//关闭释放映射区
return 0;
}
读进程代码:
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<string.h>
struct STU{
int id;
int name[20];
char sex;
};
void sys_err(char *str){
perror(str);
exit(-1);
}
int main(int argc, char *argv[]){
int fd; // 文件描述符
struct STU student;
struct STU *mm;
if(argc < 2){
printf("./a.out file_shared\n");
exit(-1);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1) sys_err("open error");
mm = (struct STU*)mmap(NULL, sizeof(student), PROT_READ, MAP_SHARED, fd, 0);//创建映射区
if(mm == MAP_FAILED)//创建映射区失败
sys_err("mmap error:");
close(fd);//关闭文件
while(1){
printf("id = %d\t name = %s\t %c\n", mm->id, mm->name, mm->sex);//回显
sleep(2);
}
munmap(mm, sizeof(student));
return 0;
}
效果演示:
一个终端执行 ./mmap_w file_shared
运行成功:
另外一个终端执行 ./mmap_r file_shared
运行效果:
会一直跟创建的映射区进行读操作,实现了无血缘关系进程的通信操作。
另外还要记住一个 strace 命令可以查看 可执行文件的所使用的系统调用。