1. 为什么需要 IPC
每个进程都有自己独立的虚拟地址空间,一个进程无法直接访问另一个进程的内存。但实际开发中,进程之间经常需要共享数据或交换信息,例如:
- 父进程把任务分发给子进程,子进程把结果回传给父进程;
- 多个进程协作处理同一份数据;
- 一个进程负责采集数据,另一个进程负责计算或落盘。
这种「进程之间传递数据、同步状态」的机制,统称为IPC(Inter-Process Communication,进程间通信)。
2. IPC 的常见种类
- 古老的通信方式:无名管道(pipe)、有名管道(FIFO)、信号(signal);
- System V / POSIX IPC:共享内存、消息队列、信号量集;
- 网络通信:socket,既能本机通信,也能跨主机通信。
本文重点梳理管道这一类,也就是无名管道和有名管道。
3. 无名管道(pipe)
无名管道 ===》pipe ==》只能给有亲缘关系进程通信
管道的特性:
1、管道是 半双工的工作模式 , 实际编程使用,会当单工使用。
2、所有的管道都是特殊的文件不支持定位操作。lseek->> fd fseek ->>FILE*
3、管道是特殊文件,读写(首选)使用文件IO ,open,read,write,close; 可选(标准io带缓存区)
fgets,fread,fgetc,
编程顺序:创建管道 ==》fork–>读写管道 ==》关闭管道
读端与写端
1,读端存在,一直向管道中去写,超过64k,写会阻塞, 写段写的太快
2,写端是存在的,读管道,如果管道为空的话,读会阻塞。 读段读的太快
3,管道破裂,读端关闭,写管道,会导致写段退出
4, read 0 ,写端关闭,如果管道没有内容,read 0 ; 进程间通信结
创建无名管道函数
int pipe(int pipefd[2]);
功能:创建并打开一个无名管道
参数:pipefd[0] ==>无名管道的固定读端
pipefd[1] ==>无名管道的固定
返回值:成功 0
失败: -1;
代码示例:
``
4. 有名管道(FIFO)
4.1 为什么需要有名管道
无名管道只能用于亲缘进程,一旦两个进程毫无关系(比如两个独立启动的程序),就无法共享同一个管道。有名管道在文件系统中有一个路径名,任何进程只要知道这个路径,就能打开它进行通信。
4.2 特点
在文件系统中以特殊文件形式存在,用 ls -l 可以看到类型为 p;
可以用于任意进程之间通信,不要求亲缘关系;
数据同样存在于内核缓冲区,进程退出后数据消失;
依然是单向的,需要双向通信时通常创建两个 FIFO;
打开 FIFO 时,读端和写端会互相阻塞等待对方打开(除非使用 O_NONBLOCK)。
有名管道 ===》fifo ==》可以给任意单机进程通信 .有文件名称的管道。文件系统中可见
和无名管道特性一致。 额外的, 如果有一端没有打开,则默认在open函数部分阻塞
编程步骤: 创建有名管道 》打开有名管道 ==》读写管道》关闭管道 ==》卸载有名管道
有名管道的函数
int mkfifo(const char *pathname, mode_t mode);
功能:在指定的pathname路径+名称下创建一个权限为
mode的有名管道文件。
参数:pathname要创建的有名管道路径+名称
mode 8进制文件权限。
返回值:成功 0
失败-1;
有名管道间传输png文件代码示例:
1.读端代码:
2.写端代码:
5. 无名管道与有名管道对比
| 对比项 | 无名管道 pipe | 有名管道 FIFO |
|---|---|---|
| 是否有名字 | 无 | 有,存在于文件系统 |
| 适用进程 | 仅亲缘进程 | 任意进程 |
| 创建方式 | pipe() | mkfifo() 或 mkfifo`命令 |
| 数据存储 | 内核缓冲区 | 内核缓冲区 |
| 通信方向 | 单向 | 单向 |
| 生命周期 | 随进程关闭而消失 | 文件节点保留,需手动删除 |
- 无名管道适合父子进程之间简单、临时的数据传递,使用简单但受限于亲缘关系;
- 有名管道通过文件系统路径解耦了进程关系,适合两个独立程序之间的通信;
- 两者都是单向字节流,需要双向通信时要成对使用,或者考虑 socketpair、共享内存等方案。