进程间通信方式(2021.2.7)
本质:内核空间中的一块缓冲区
-
- 管道(使用最简单)
-
- 信号(开销最小)
-
- 共享映射区(无血缘关系)
-
- 本地套接字(最稳定)
管道
实现原理:内核借助环形队列机制,使用内核缓冲区实现
特质:
1.伪文件
2.管道中的数据只能一次读取
3.数据在管道中,只能单向流动
局限性:
1、自己写,不能自己读
2、数据不可以反复读
3、双向半单工通信
4、血缘关系进程可用
pipe函数: 创建,并打开管道
int pipe(int fd[2]);
参数:
fd[0]:读端
fd[1]:写端
返回值:
成功:0
失败:-1
管道的读写行为:
一、读管道
1.管道中无数据,
1)无写端,read返回00::
2)有写端,read阻塞等待
2.管道有数据,read返回实际读到的字节数
二、写管道
1.无读端,异常终止。(SIGPIPE导致的)
2.有读端:
1)管道已满,阻塞等待
2)管道未满,返回写出的字节个数
pipe管道:
父子进程通信
兄弟进程通信
fifo管道:
无血缘关系进程通信
命名管道:mkfifo
文件实现进程间通信:
打开的文件是内核中的一块缓冲区。多个无血缘关系的进程,可以同时访问该文件
共享内存映射
mmap映射
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
参数:
addr:指定映射区的首地址。通常传NULL,表示让系统自动分配
length:共享内存映射区的大小
prot:共享内存映射区的读写属性。PROT_READ,PROT_WRITE, PROT_READ|PROT_WRITE
flags:标注共享内存的共享属性。MAP_SHARED,MAP_PRIVATE
fd;用于创建共享内存映射区的那个文件的 文件描述符
offset:偏移位置(4k的整数倍)
返回值:
成功:映射区的首地址
失败:MAP_FAILED,,errno
使用注意事项:
1.用于创建映射区文件的大小为0,实际指定非0大小创建映射区,出 总线错误
2.用于创建映射区文件的大小为0,实际指定0大小创建映射区,出 无效参数错误
3.用于创建映射区的文件读写属性为 只读 ,映射区属性
4.创建映射区,需要read权限。mmap的读写权限,应该<=文件的open权限。只写不行
5.文件描述符fd,在mmap创建映射区完成即可关闭。后续访问文件,用 地址访问 没有问题
6.offset必须是4096的整数倍。(MMU映射的最小单位 4k)
7.对申请的映射区内存,不能越界访问
8.munmap用于释放的地址,必须是nmap申请返回的地址
9.映射区访问权限为”私有“MAP_PRIVATE,对内存所做的所有修改,只在内存中有效
10.映射区访问权限为”私有“MAP_PRIVATE,只需要open文件时,有读权限,用于创建映射区即可
mmap函数的保险调用方式:
1.fd=open("文件名",O_RDWR)
2.mmap(NULL,有效文件大小,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
父子进程使用 mmap进程间通信:
1.父进程创建映射区。open(O_RDWR) mmap();
2.指定MAP_SHARED权限
3.fork()创建子进程
4.一个进程读,另外一个进程写
5.使用munmap(p,len)关闭
无血缘关系进程间mmap通信:
两个进程 打开同一个文件,创建映射区
指定flags为MAP_SHARED
一个进程写入,另外一个进程读出
【注意】:
无血缘关系进程间通信。
mmap:数据可以重复读取
fifo:数据只能一次读取
mmap匿名映射区
参数:
flags:MAP_ANONYMOUS
p=(int*)mmap(NULL,40,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANNOYMOUS,-1,0);
当操作系统不支持该参数时
fd=open("/dev/zero",O_RDWR);
p=(int*)mmap(NULL,40,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANNOYMOUS,fd,0);