Linux 无名管道
在 Linux 系统中,进程间通信(IPC) 是一个非常重要的主题,而管道(pipe)是一种常用的通信方式。本教程将带你深入了解 无名管道(unnamed pipe) 的原理和使用方法。你将学会如何在父子进程之间使用无名管道传递数据,掌握 pipe()
函数的用法,并通过完整示例了解数据流的过程。无名管道简单、高效,是进程通信入门的最佳方式。
什么是无名管道?
无名管道是一种 单向通信机制,用于具有亲缘关系的进程之间的数据传输(例如父进程和子进程)。它具有以下特点:
- 只能在创建它的进程及其子进程之间通信。
- 数据只能单向流动。
- 使用内核缓冲区,读写方式类似文件。
pipe() 函数介绍
在 C 语言中使用无名管道的关键函数是 pipe()
,函数原型如下:
int pipe(int pipefd[2]);
说明:
pipefd[0]
:用于读取数据(读端)pipefd[1]
:用于写入数据(写端)- 成功返回 0,失败返回 -1
基本使用流程
使用无名管道的一般步骤如下:
- 创建管道:
pipe(fd)
- 创建子进程:
fork()
- 父进程写入数据到
fd[1]
,子进程从fd[0]
读取(或反过来) - 使用完管道后关闭不需要的读写端(防止死锁)
- 使用
read()
和write()
进行通信
无名管道示例:父子进程通信
下面是一个完整示例,父进程向子进程发送一段消息。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main() {
int pipefd[2];
pid_t pid;
char buffer[100];
if (pipe(pipefd) == -1) {
perror("pipe 创建失败");
return 1;
}
pid = fork();
if (pid < 0) {
perror("fork 创建失败");
return 1;
}
if (pid == 0) {
// 子进程:读取数据
close(pipefd[1]); // 关闭写端
read(pipefd[0], buffer, sizeof(buffer));
printf("子进程收到信息:%s\n", buffer);
close(pipefd[0]);
} else {
// 父进程:写入数据
close(pipefd[0]); // 关闭读端
char *msg = "你好,子进程!";
write(pipefd[1], msg, strlen(msg) + 1); // 记得写入字符串结束符 '\0'
close(pipefd[1]);
}
return 0;
}
运行结果:
子进程收到信息:你好,子进程!
注意事项
- 使用管道前必须先调用
pipe()
函数初始化两个文件描述符。 - 管道是单向通信的,如果需要双向通信,需要建立两个管道。
- 要关闭不需要的读/写端,否则容易导致进程阻塞。
- 传输的数据大小不宜超过内核缓冲区(通常为几 KB),否则
write()
会阻塞。
小结
通过本节内容,你已经学会了什么是无名管道,它的创建方法和通信原理。你了解了如何在父子进程之间使用 pipe()
、fork()
、read()
和 write()
实现进程间通信。虽然无名管道只支持单向传输和具有亲缘关系的进程,但它是 Linux IPC 的基础之一,为你后续学习命名管道、共享内存等打下了坚实的基础。