跳到主要内容

Linux 无名管道

在 Linux 系统中,进程间通信(IPC) 是一个非常重要的主题,而管道(pipe)是一种常用的通信方式。本教程将带你深入了解 无名管道(unnamed pipe) 的原理和使用方法。你将学会如何在父子进程之间使用无名管道传递数据,掌握 pipe() 函数的用法,并通过完整示例了解数据流的过程。无名管道简单、高效,是进程通信入门的最佳方式。

什么是无名管道?

无名管道是一种 单向通信机制,用于具有亲缘关系的进程之间的数据传输(例如父进程和子进程)。它具有以下特点:

  1. 只能在创建它的进程及其子进程之间通信。
  2. 数据只能单向流动。
  3. 使用内核缓冲区,读写方式类似文件。

pipe() 函数介绍

在 C 语言中使用无名管道的关键函数是 pipe(),函数原型如下:

int pipe(int pipefd[2]);

说明:

  • pipefd[0]:用于读取数据(读端)
  • pipefd[1]:用于写入数据(写端)
  • 成功返回 0,失败返回 -1

基本使用流程

使用无名管道的一般步骤如下:

  1. 创建管道:pipe(fd)
  2. 创建子进程:fork()
  3. 父进程写入数据到 fd[1],子进程从 fd[0] 读取(或反过来)
  4. 使用完管道后关闭不需要的读写端(防止死锁)
  5. 使用 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 的基础之一,为你后续学习命名管道、共享内存等打下了坚实的基础。

知心 MBTI 微信小程序
「知心MBTI」微信小程序,探索你的 MBTI 人格类型,发现潜能。微信扫码免费测试 🎉