2026/10/24 7:51:40
网站建设
项目流程
Linux进程间通信‑管道(无名管道&有名管道)
一、无名管道 pipe
核心特性
- 只支持有亲缘关系进程通信:父子、兄弟进程。没有实体文件,仅存在内核。
- 单向半双工:pipe得到两个文件描述符, pipefd[0] 读端, pipefd[1] 写端。数据只能单向流动,双向通信要创建两组管道。
- 必须先调用 pipe() 创建管道,再 fork() ,子进程复制父进程的文件描述符,才能通信。
管道阻塞规则
- 管道有写端存在
- 有数据: read 直接读出数据
- 无数据: read 阻塞休眠,等待对方write写入数据
- 所有写端全部关闭
- 有残留数据:读完现有数据
- 无数据: read 返回0,代表读到末尾,不会阻塞
- 管道有读端存在
- 缓冲区未满(管道默认64KB): write 直接写入
- 缓冲区写满: write 阻塞,等待读端取走数据
- 所有读端全部关闭
- 进程执行 write ,触发管道破裂SIGPIPE信号,程序直接异常退出。
关键点:写端、读端的打开关闭状态,直接决定read/write是阻塞、返回0还是程序崩溃。
二、有名管道 FIFO(mkfifo)
核心特性
- 支持任意两个进程通信,不需要亲缘关系。会在磁盘生成p类型管道文件,但磁盘不存数据,数据仍然存放在内核缓冲区。
- open行为特殊:必须读写两端同时打开成功,open函数才会返回;只打开一端,程序阻塞等待另一端进程打开管道。这也是写代码最容易踩坑的地方。
- 同样单向,双向聊天必须两条有名管道,一条A写B读,一条B写A读。
接口
int mkfifo(const char *pathname, mode_t mode);
- pathname:管道文件路径;mode权限。
- 返回0成功,‑1失败。
重复执行mkfifo,文件已存在会报错,可以忽略该错误,不影响后续open。
三、无名管道 vs 有名管道对比
- 无名管道pipe
- 无磁盘文件;仅限亲缘进程;先pipe后fork;shell | 底层就是无名管道。
- 有名管道mkfifo
- 磁盘存在管道文件;任意进程;open会阻塞;双向通信需要两组FIFO。
重点总结
- pipe无名管道:只能父子进程,没有实体文件,通信依赖fork复制fd。牢记4条read/write阻塞规则,SIGPIPE管道破裂是高频考点。
- mkfifo有名管道:任意进程可通信;open会阻塞等待两端;双向聊天必须两条管道。
- 管道属于字节流,不识别行,消息边界靠程序自己约定(常用 \n 换行)。
- 代码易错点:FIFO不要单边open,路径要完全一致,mkfifo重复调用报错可以忽略。
- 当所有读端关闭,继续write → SIGPIPE,进程直接退出;所有写端关闭,read返回0。