在Linux系统中,进程间通信(IPC)是一个核心概念。Linux匿名管道是最古老也是最常用的IPC方式之一。它允许具有亲缘关系的进程(如父子进程)以流的形式单向传递数据。本文将从pipe系统调用出发,深入剖析其原理,并提供完整的可运行代码示例,帮助你从零掌握管道通信。
pipe函数原型定义在中:
int pipe(int pipefd[2]); 调用成功时返回0,失败返回-1。参数pipefd返回两个文件描述符:pipefd[0]为读端,pipefd[1]为写端。数据从写端写入,从读端读出,遵循FIFO原则。
下面是一个完整的示例,父进程向子进程发送消息:
#include #include #include #include int main() { int pipefd[2]; pid_t pid; char buf[1024]; const char *msg = "Hello from parent!"; if (pipe(pipefd) == -1) { perror("pipe"); return 1; } pid = fork(); if (pid == -1) { perror("fork"); return 1; } if (pid == 0) { // 子进程:读管道 close(pipefd[1]); // 关闭写端 read(pipefd[0], buf, sizeof(buf)); printf("子进程收到:%s", buf); close(pipefd[0]); } else { // 父进程:写管道 close(pipefd[0]); // 关闭读端 write(pipefd[1], msg, strlen(msg) + 1); close(pipefd[1]); wait(NULL); // 等待子进程结束 } return 0;} 编译运行:gcc pipe_demo.c -o pipe_demo && ./pipe_demo,输出:子进程收到:Hello from parent!。这个简单的例子展示了进程间通信的核心流程:创建管道、fork、关闭无关端、读写数据。
匿名管道在内核中本质是一个环形缓冲区(ring buffer),基于pipefs文件系统。每次write将数据拷贝到缓冲区,read从缓冲区拷贝数据。当缓冲区满时,写操作阻塞;缓冲区空时,读操作阻塞。下图展示了管道的核心结构:
管道的生命周期与文件描述符关联:只有当所有指向管道的读端和写端都关闭后,管道才会被销毁。这正是为什么在fork后要立即关闭不需要的端。
我们可以通过修改代码来测试阻塞特性。例如,让写端写入超过缓冲区大小的数据(Linux默认管道缓冲区大小通常是65536字节,可通过fcntl调整),观察写阻塞。下面是一个测试写阻塞的片段:
// 写端写入大量数据char huge[70000];memset(huge, "A", sizeof(huge));write(pipefd[1], huge, sizeof(huge));printf("写入完成"); 如果读端不及时读取,写操作会在缓冲区满后阻塞,直到有空间可用。这正是管道读写测试中需要关注的同步机制。
通过本文,你应该已经掌握了从pipe系统调用到实际通信测试的完整流程。动手运行代码,深入理解内核原理,你将在Linux编程之路上更进一步。
—— 专注于Linux进程间通信系列
本文由主机测评网于2026-02-19发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20260225931.html