032 进程间通信 —— 有名管道篇

AI-摘要
小米里的大麦 GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
032 进程间通信 —— 有名管道篇
小米里的大麦进程间通信 —— 有名管道篇
1. 什么是有名管道
1. 基本定义
有名管道是 Linux 中的一种进程间通信方式,其本质也是一个特殊类型的文件,存在于文件系统中,支持 无亲缘关系的进程 之间的数据通信。
2. 与匿名管道的对比
特性 | 匿名管道(pipe) | 有名管道(FIFO) |
---|---|---|
是否有文件路径 | ❌ 没有 | ✅ 有(存在于文件系统中) |
是否只能父子进程通信 | ✅ 是 | ❌ 可以无亲缘关系通信 |
创建方式 | pipe() |
mkfifo() / mknod() |
常见用途 | 父子进程、线程内通信 | shell 脚本、后台服务通信 |
2. 有名管道的创建与使用
1. mkfifo
函数原型 —— 创建有名管道
1 |
|
参数详解
const char *pathname
: 表示希望创建的 有名管道的路径(通常是绝对路径或当前目录下的文件名)。它创建出来的是一个 文件系统中的特殊设备文件,使用ls -l
可以看到文件类型为p
(pipe):
1 | prw-r--r-- 1 user user 0 Jun 21 14:00 myfifo |
mode_t mode
: 表示新创建的 FIFO 文件的权限,常用类似 shell 中的权限位(与chmod
相同),如:0666
:所有用户可读写(不加执行权限)。0644
:仅拥有者可写,其它用户只读。0600
:仅拥有者可读写。
注意:这个权限会受到 umask(用户掩码) 的影响!
返回值
- 成功时:返回 0。
- 失败时:返回 -1,并设置 errno 表示错误原因。
通信 Demo:
创建一个有名管道文件 myfifo
,使用 while :; do echo "Hello Linux" ; sleep 1; done >> myfifo
循环写入内容,发现管道文件大小始终是 0。实验演示 | B 站。说明:FIFO 是一种特殊文件,用于进程通信,其内容不保存在磁盘上,而是临时存放在内存缓冲区中,并且只有当有读端存在时,写入操作才能成功。即使有数据写入,文件大小也始终显示为 0。
2. unlink
函数原型 —— 删除有名管道(本质就是从文件系统里删掉一个文件)
1 |
|
参数: 要删除的文件(或管道、socket 文件等)的路径名,支持相对路径或绝对路径。
返回值:
- 成功:返回 0
- 失败:返回 -1,并设置全局变量 errno
重点理解
unlink()
不会管里面有没有读写端打开,只是把文件名从文件系统中移除。- 如果此时还有进程打开这个管道文件,管道内内核资源还在用,直到所有引用关闭后,内核才真正释放资源。(和普通文件 inode 行为一样)
3. unlink
和 rm
的关系
unlink()
是 Linux 内核提供的低级系统调用,直接作用于文件系统的 inode 链接数。rm
是用户空间程序,底层就是调用unlink()
来完成删除。
在实际生产场景中:
- 有名管道通常是 临时文件,由程序创建出来给进程通信用。
- 程序结束时,最好自己负责清理掉。
- 如果不主动
unlink()
,就要依赖人去rm
,这就是“脏文件”了 —— 下次mkfifo
会报EEXIST
。
操作 | 作用 | 场景 |
---|---|---|
rm |
命令行层面的文件删除 | 人工手动操作 |
unlink() |
系统调用层面的文件删除 | 程序自动管理资源,退出时清理 |
本质是一样的,只是执行主体和使用时机不同。
思考:你知道
rm
删除文件背后的原理吗?如果文件还被打开,rm
会发生什么?答案:
rm
会把文件名目录项删除,但是只要还有进程打开这个文件,inode 不会被释放。- 所以有名管道如果还有进程在读写,
rm
(或unlink
)后文件看不到了,但内核仍然维护着,直到最后一个 fd 关闭,内核才真正释放。
3. 基于有名管道通信的服务端-客户端模型 Demo
1. 头文件 comm.hpp
1 |
|
2. 客户端 Client.cc
1 |
|
3. 服务端 Server.cc
1 |
|
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果