进程间通信
IPC:InterProcess Communication 进程间通信,通过内核提供的缓冲去进行数据交换的机制
IPC通讯的方式有几种:
- pipe管道 最简单
- fifo 有名管道
- mmap 文件映射共享IO 速度最快
- 本地soket最稳定
- 信号携带信息量最小
- 共享内存
- 消息队列
PIPE 通信
常见的通行方式:单工(广播,单向传播),半双工(对讲机,可以双向,但不可以同时发生),全双工(打电话,双向传播,可以同时发生)
管道:半双工通信
管道函数:
int pipe(int pipefd[2]);
pipefd读写文件描述符,0代表读,1代表写
返回值:失败返回-1,成功返回0
父子进程实现pipe通信,实现 ps aux|grep bash功能
代码的问题:
认为父进程认为还有写端存在,就有可能还有人给发数据。,继续等待
读管道:
- 写端全部关闭 read读到0,相当于读到文件末尾
- 写端没有全部关闭
– 有数据 read读到数据
– 没有数据 read阻塞 fcntl函数可以更改非阻塞
写管道:
- 读端全部关闭 产生一个信号SIGPIPE,程序一场终止
- 读端未全部关闭
– 管道已满 write阻塞
– 管道未满 write正常写入
计算管道大小 512*8
long fpathconf(int fd,int name);
ulimit -a
优点:
简单
缺点:
- 只能有血缘关系的进程通信
- 父子进程单方向通信,如果需要双向通信,需要创造很多根管道
FIFO通信
FIFO有名管道,实现无血缘关系进程通信
- 创建一个管道的伪文件
– mkfifo myfifo 命令创建
– 也可以用函数 int mkfifo(const char *pathname,mode_t mode); - 内核会针对fifo文件开辟一个缓冲区,操作fifo文件,可以操作缓冲区,实现进程间通信 实际上就是文件读写
open注意事项,打开fifo文件的时候,read端会阻塞等待write端open,write端同理,也会阻塞等待另外一端打开
创建映射区
void *mmap(void *addr,size_t length,int flags,int fd,off_t offset);
- addr传NULL
- length 映射区的长度
- prot
– PROT_READ 可读
– PROT_WRITE可写 - flags
– MAP_SHARED 共享的
– MAP_PRIVATE 私有的 - fd文件描述符,open打开一个文件
释放映射区
int munmap(void *addr,size_t length);
1.如果更改mem变量的地址,释放的时候 munmap,传入mem还能成功吗?
不能!!!
2.如果对mem越界操作会怎么样?
文件的大小对映射区操作有影响,尽量避免。
3.如果文件偏移量随便填个数会怎么样?
offse必须是4k的整数倍
4.如果文件描述符先关闭,对mmap映射有没有影响?
没有影响
5.open的时候,可以新创建一个文件来创建映射区吗?
不可以用大小为0的6.open文件选择_WRONLY,可以吗?
不可以: Permission denied
7.当选择 MAPSHARED的时候,open文件选择O_RDONLY,prot可以选择PRO TREADPROT_WRITE吗?
Permission denied, SHARED的时候,映射区的权限<open文件的权限
8.mmap什么情况下会报错?
很多情况
9.如果不判断返回值会怎么样?
会死的和难堪