简介
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
IPC的方式通常有管道(包括无名管道和命名管道)、信号、消息队列、信号量、共享内存、套接字。
其中信号的介绍可查看该文《Linux信号》
本文重点介绍管道的概念以及使用方式。
无名管道
概念
最基本的进程间通信方式,从本质上说,管道是一种特殊的文件,存在于内存中,但是它没有名字,只能用于有亲缘关系的进程间(fork)。
实现机制
管道是由内核管理的一个缓冲区,它的一端连接一个进程的输出,另一端连接一个进程的输入。管道的缓冲区不需要很大,它被设计为环形的数据结构,当两个进程都终止后,管道的生命周期也会被结束。
特点
- 半双工,数据只能在一个方向上流动,若要双向通信,需要建立两个管道
- 只能在具有公共祖先的进程之间使用,通常是
fork
的父子进程之间使用管道通信 - 管道中的数据遵循先入先出的原则
- 管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式
- 管道不是普通的文件,不属于某个文件系统,其只存在于内存中,对应一块缓冲区,不同系统大小不一定相同
- 管道数据被读走后抛弃,为了释放空间以便写更多数据
读写规则
阻塞性:
- 默认用
read
函数读数据是阻塞(无数据时)的,write
函数也是阻塞的(当管道满了时) - 可通过
functl
来改变阻塞特性,如
funtl(fd,F_SETFL,0);
设为阻塞
funtl(fd,F_SETFL,0_NOBLOCK);
设为非阻塞
- 默认用
退出:
- 当写一个读端口已被关闭的管道时,写进程会收到SIGPIPE信号(默认退出,若从信号处理函数返回后则
write
函数出错返回,errno=EPIPE) - 当读一个写端口已被关闭的管道时,在所有数据都被读取后,
read
返回0,以指示达到了文件结束处
- 当写一个读端口已被关闭的管道时,写进程会收到SIGPIPE信号(默认退出,若从信号处理函数返回后则
函数
1 | int pipe(int pipefd[2]); |
常用方式如下:

代码如下:
1 | int |
命名管道(FIFO)
与无名管道的区别
不相关的进程之间也能交换数据
当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用
注意:创建命名管道一定要用指定函数创建,不能新建一个文件,因为命名管道是特殊的文件,如果对管道文件进行复制,会变成普通文件,不具有管道的特点
读写规则
- 阻塞性:
- 一般情况中(open时未指定O_NOBLOCK),当你用只读/只写方式打开FIFO的时候会阻塞,直到其他进程用只写/只读方式打开该FIFO
- 如果指定了O_NOBLOCK,则只读打开立即返回。但是,如果没有进程已经为读而打开一个FIFO,那么只写打开将出错返回,其errno是ENXIO。
- 退出:
- 类似于管道,若写一个尚无进程为读而打开的FIFO,则产生信号SIGPIPE。
- 若某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志
函数
1 | int mkfifo(const char *pathname, mode_t mode); |