题目
使用管道实现父子进程间通信
信息
- 类型:问答
- 难度:⭐
考点
管道原理,父子进程通信,文件描述符
快速回答
在父子进程间使用管道通信的核心步骤:
- 父进程调用
pipe()创建管道,获得两个文件描述符 - 父进程调用
fork()创建子进程 - 父进程关闭读端,向写端发送数据
- 子进程关闭写端,从读端接收数据
- 双方通信完成后关闭文件描述符
原理说明
管道是Unix/Linux中最基础的进程间通信机制,本质是内核维护的环形缓冲区。特点:
- 单向通信:数据只能从写端流向读端
- 血缘关系:仅适用于父子进程等有亲缘关系的进程
- 字节流传输:无消息边界,按写入顺序读取
代码示例(C语言)
#include <unistd.h>
#include <stdio.h>
int main() {
int fd[2]; // fd[0]:读端, fd[1]:写端
char buf[20];
// 1. 创建管道
if (pipe(fd) == -1) {
perror("pipe");
return 1;
}
// 2. 创建子进程
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return 1;
}
if (pid > 0) { // 父进程
close(fd[0]); // 关闭读端
write(fd[1], "Hello child!", 12); // 写入数据
close(fd[1]); // 关闭写端
} else { // 子进程
close(fd[1]); // 关闭写端
read(fd[0], buf, sizeof(buf)); // 读取数据
printf("Received: %s\n", buf);
close(fd[0]); // 关闭读端
}
return 0;
}最佳实践
- 及时关闭未用描述符:父子进程需立即关闭不需要的端口,避免资源泄漏
- 检查返回值:所有系统调用都应检查错误返回值
- 同步控制:复杂场景需配合
wait()等同步机制
常见错误
- 忘记关闭描述符:导致进程无法检测到EOF,造成阻塞
- 双向通信未用两个管道:单管道只能单向通信,双向需创建两个独立管道
- 未处理阻塞:读写操作默认阻塞,需考虑非阻塞模式或超时机制
扩展知识
- 命名管道(FIFO):通过文件系统可见,允许无亲缘关系进程通信
- 管道容量:Linux默认64KB,写满时
write()阻塞,读空时read()阻塞 - 替代方案:进程无亲缘关系时,可考虑消息队列或套接字