UNIX进程间通信方式总结
为什么需要进程间通信
进程的通信需求包括:数据传输、共享数据、通知事件、资源共享、进程控制。 每个进程具有一个虚拟内存地址空间,除了共享内存区之外不能互相访问,因此需要通过内核或者外设进行通信。
UNIX标准和实现
由于接下来会讲到XSI和System V,所以先理一下各种UNIX标准和实现
名称 | 标准/实现 | 组织 | 备注 |
---|---|---|---|
POSIX | 标准 | IEEE | 定义了必选和可选接口,XSI就是可选接口标准 |
SUS | 标准 | Open Group(拥有UNIX商标) | SUS是POSIX的超集 |
SVR4(UNIX System V Release 4) | 实现 | AT&T | |
4.4BSD(Berkeley Software Distribution) | 实现 | 加州大学伯克利分校 | |
Linux | 实现 | 开源社区 | |
Mac OS X | 实现 | 苹果公司 |
管道
#include <unistd.h>
int pipe(int fd[2]);
- 只能用于有亲缘关系的两个进程间通信(也可以用于有亲缘关系的线程间通信),数据只能在一个方向上流动,fd[0]用于读,fd[1]用于写。
- 内核为管道维护了一个缓冲区,写入管道的数据写到这块内核缓冲区中。当管道的读端和写端都被关闭后,这块内核缓冲区也就被释放了。PIPE_BUF规定了管道内核缓冲区的大小。
- 管道需要读写双方同时“在线”:如果读一个写端关闭的管道,当所有数据读取完之后read返回0表示文件结束;如果写一个读端已关闭的管道,产生SIGPIPE信号,write返回-1,errno设置为EPIPE。
- 应用实例:shell的管道命令|,但只能线性连接
命名管道FIFO
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
- 可以用于任意进程间通信,可以有多个写进程多个读进程(也可以用于任意、多个线程间通信),但是如果不想多个写进程写的数据交叉就需要考虑原子操作。
- 是一种文件类型,在文件系统中有节点,但是不真正占有磁盘空间,而是具有一块内核缓冲区,这块内核缓冲区的大小限制为PIPE_BUF。可以像管理文件权限一样管理这个FIFO的权限。
- 命名管道被创建之后,需要使用open()打开。open一个FIFO时是否设置O_NONBLOCK的区别:若设置,只读open要阻塞到某个进程为写而打开这个FIFO,只写open要阻塞到某个进程为读而打开这个FIFO。若未设置,只读open立即返回,只写open返回-1并且errno设置ENXIO。
- unlink()会在对这个文件系统节点的引用减为0后删除这个文件系统节点(彻底删除FIFO)。
- 实例:shell命令输出流的非线性连接(一