Linux 基础入门操作 第九章 进程间通信之有名管道
1 有名管道介绍
有名管道(Named Pipe),也称为 FIFO(First In First Out),是 Linux 进程间通信(IPC)的一种方式。FIFO 不同于管道之处在于它提供一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中。这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信(能够访问该路径的进程以及 FIFO 的创建进程之间),因此,通过 FIFO 不相关的进程也能交换数据。
它与匿名管道的核心区别在于:
-
匿名管道 仅适用于 有亲缘关系的进程(如父子进程),而 有名管道 允许 任意进程(即使无亲缘关系)通过文件系统路径进行通信。
-
有名管道 在文件系统中有一个 持久化的节点(类似于文件),而匿名管道是临时的,仅存在于内存中。
2 shell 编程应用
- 打开一个 终端A 发送信息
# 创建命名管道
mkfifo mypipe
# 进程 A 写入数据
echo "Hello from Process A" > mypipe
- 打开一个终端B 接收信息
# 进程 B 读取数据
cat mypipe
- 在终端A或者终端B中要删除有名管道,需要手动删除
rm mypipe
3 进程中有名管道用到函数
3.1 mkfifo 函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int mkfifo(const char * pathname, mode_t mode)
- 其中输入形参:
pathname:FIFO 文件的路径(如 “/tmp/myfifo”)。
mode:权限模式(如 0666,表示所有用户可读写), mkfifo()建立的 FIFO 文件其他进程都可以用读写一般文件的方式存取。
具体案例如下:
mkfifo("/tmp/myfifo", S_IFIFO | 0666); // S_IFIFO 可省略,因 mkfifo 已隐含
- 返回值:
成功返回 0,失败返回 -1 并设置 errno。 - mkfifo()会依参数 pathname 建立特殊的 FIFO 文件,该文件必须不存在。
3.2 删除函数
- 可以利用停止信号,来触发删除函数,否则需要手动删除
unlink(const char * pathname); // 删除 FIFO 文件
- 有可能存在残留的情况,最好程序启动的时候,删除残留。
if (access("/tmp/myfifo", F_OK) == 0) {
unlink("/tmp/myfifo");
}
3.3 其它文件操作函数说明
- 只读方式打开,默认阻塞模式
int fd = open("/tmp/myfifo", O_RDONLY ); // 阻塞模式打开
- 只读方式打开,采用非阻塞方式
int fd = open("/tmp/myfifo", O_RDONLY | O_NONBLOCK); // 非阻塞模式打开
- 以只写方式打开,默认采用阻塞模式
int fd = open("/tmp/myfifo", O_WRONLY ); // 阻塞模式打开
如果没有写入端,open() 会 立即返回 -1,并设置 errno = ENXIO。
3.4 阻塞与非阻塞模式说明
3.5 注意事项
-
需要轮询(polling)的 IPC 通信。
-
避免死锁(如双向通信时双方都在等待对方)。
-
如果需要双工通讯,需要创建两个管道。
3.6 总结
4 代码演示
4.1 单工通讯
4.1.1 发送端
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#define FIFO_PATH "/tmp/myfifo"
int ma