进程间通信
常见IPC方法
管道:使用简单
FIFO:非血缘关键间
信号:开销小
共享内存:非血缘关系间
本地套接字:稳定性好
…
管道
特性
- 伪文件(内核缓冲区)
- 两个文件描述符(r/w)
- 数据从写端流入,读端流出
原理
- 内核缓冲区
- 环形队列
局限性
- 进程自己写不能自己读
- 数据不能反复读
- 单向通信(半双工)
- 只能用于有公共祖先的进程间
pipe函数
-
参数
- fd2
-
返回值
-
成功:0
-
失败:
- -1
- errno
-
管道读写行为
-
读管道
-
管道中有数据
- read返回实际读到的字节数
-
管道中无数据
- 写端全关闭:read返回0
- 仍有写端打开:阻塞等待
-
-
写管道
-
读端全关闭
- 进程异常终止(SIGPIPE信号)
-
有读端打开
- 管道未满:写数据,返回写入字节数
- 管道已满:阻塞(少见)
-
-
父子进程间通信 ls | wc -l
-
兄弟进程间通信
获取管道缓冲区大小
- 命令:ulimit -a
- 函数: fpathconf 参2:__PC_PIPE_BUF
管道优劣
-
优点:实现手段简单
-
缺点:
- 单向通信
- 只能有血缘关系进程间使用
FIFO
命名管道(Linux基础文件类型)
创建
-
命令:mkfifo
-
函数:mkfifo
-
参数:
- name
- mode:8进制
-
返回值:
- 成功:0
- 失败:-1,设置errno
-
无血缘关系进程间通信
- 使用同一FIFO
- 可多读端,多写端
共享存储映射
文件实现进程间通信
- fork后父子进程共享文件描述符
- 无血缘关系进程打开同一文件
存储映射I/O
-
借助文件创建映射内存
-
mmap函数
-
参数:
-
addr: 建立映射区的首地址 (NULL内核自动分配)
-
length: 欲创建映射区的大小
-
prot:
- PROT_READ
- PROT_WRITE
- PROT_READ|PROT_WRITE
- …
-
flags:
- MAP_SHARED
- MAP_PRIVATE
- MAP_ANONYMOUS/MAP_ANON
-
fd: 文件描述符
-
offset:映射偏移(4K整数倍)
-
-
返回值:
-
成功:
- 映射区首地址
-
失败:
- MAP_FAILED
- 设置errno
-
-
-
munmap函数
-
参数:
- mmap返回值
- 映射区大小
-
返回值:
-
成功:
- 0
-
失败:
- -1
- 设置errno
-
-
-
使用注意事项:
-
- 映射区建立过程中隐含一次读操作
-
- MAP_SHARED时 映射区权限<=打开文件权限
-
- 映射区建立成功,文件即可关闭。
-
- 大小为0的文件无法创建映射区
-
- munmap参数应与mmap返回值严格对应
-
- 偏移位置必须为4k整数倍
-
- mmap返回值判断不能省略
-
父子进程间mmap通信
-
flags:
- MAP_PRIVATE: 独占映射区
- MAP_SHARED: 共享映射区
-
父子共享
- 打开文件描述符
- mmap建立的映射区(MAP_SHARED)
匿名映射
-
Linux
-
length:
- 任意
-
flags:
- MAP_ANONYMOUS
- MAP_ANON
-
fd:
- -1
-
-
类Unix
-
length:
- 任意
-
fd:
- open(/dev/zero, O_RDWR)
-
无血缘关系进程间mmap通信
- 使用同一文件创建映射区
- 指定MAP_SHARED
- 可多读端,多写端
基本概念 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信
以下几个最重要
① 管道 (使用最简单)
② 信号 (开销最小)
③ 共享映射区 (无血缘关系)
④ 本地套接字 (最稳定)
管道的优劣
优点:简单,相比信号,套接字实现进程间通信,简单很多。
缺点:1. 只能单向通信,双向通信需建立两个管道。
2. 只能用于父子、兄弟进程(有共同祖先)间通信。该问题后来使用fifo有名管道解决。
1. 其本质是一个伪文件(实为内核缓冲区)
- 由两个文件描述符引用,一个表示读端,一个表示写端。
- 规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
管道的局限性:
① 数据自己读不能自己写。
② 数据一旦被读走,便不在管道中存在,不可反复读取。
③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
④ 只能在有公共祖先的进程间使用管道。
- 规定数据从管道的写端流入管道,从读端流出。
三个作业 坐一下
本地简易聊天室 qq