news 2026/5/4 21:22:57

Linux pipe匿名管道进程间通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux pipe匿名管道进程间通信
extern int pipe (int __pipedes[2])

上面是函数原型 传入一个字符数组,创建两个文件描述符,[0]为读端[1]为写端

下面给一个代码案例,一步步解析过程

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char const *argv[]) { int pipefd[2]; //管道传入的数组 pid_t cpid; //子进程pid if(argc != 2) { printf("%s 请填写需要传递的信息\n",argv[0]); exit(EXIT_FAILURE); } if(pipe(pipefd) == -1) { perror("创建管道失败"); exit(EXIT_FAILURE); } //fork创建子进程 cpid = fork(); if(cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if(cpid == 0) { //子进程 close(pipefd[1]); //关闭读端 printf("子进程 %d 收到数据\n",getpid()); char buf; while(read(pipefd[0],&buf,1) > 0) { write(STDOUT_FILENO,&buf,1); } printf("\n"); close(pipefd[0]); //关闭读端 _exit(EXIT_SUCCESS); //系统调用关闭子进程,无需回收资源 } else { //父进程,写数据 close(pipefd[0]); //关闭读端 printf("父进程 %d 写入数据\n",getpid()); write(pipefd[1],argv[1],strlen(argv[1])); close(pipefd[1]); //写完后关闭写端 waitpid(cpid,NULL,0); //等待子进程结束 exit(EXIT_SUCCESS); } return 0; }

使用 ./unnamed_pipe_test "test" 运行代码
输出:

父进程 12259 写入数据
子进程 12260 收到数据
test

交互动画演示

1. 文件描述符 (File Descriptor, FD)

把文件描述符想象成一个遥控器

  • 内核层:操作系统内核维护着真正的“管道”对象(实际上是一块内存缓冲区)。

  • 用户层:进程手里拿的pipefd[0](值为3)和pipefd[1](值为4)只是遥控器上的按钮编号

  • pipefd[0]是 Read 按钮。

  • pipefd[1]是 Write 按钮。

  • 进程不直接操作管道内存,只能通过拿着这些号码(FD)去请求内核(read/write)。

2.fork()时的复制机制

这是理解一切的关键。

  • 当你调用fork()时,操作系统复制了父进程的PCB(进程控制块)

  • 这其中包含了文件描述符表的拷贝。

  • 可以把它想象成复印了一把钥匙。父进程手里有开门(访问管道)的钥匙,子进程复制了一把一模一样的钥匙。

  • 虽然有两把钥匙(两个不同的进程,各自有自己的 FD 表),但它们开的是同一扇门(指向同一个内核管道对象)。

3. 引用计数 (Reference Count) —— 管道生命的维持者

内核中的管道对象有一个“生命值”,这就是引用计数。它记录了“现在有多少个文件描述符指向我”。

正常流程

  • fork后,写端引用计数 = 2(父进程持有 + 子进程持有)。

  • 子进程close(pipefd[1])-> 写端引用计数降为 1。

  • 父进程写完数据。

  • 父进程close(pipefd[1])->写端引用计数降为 0

  • 核心时刻:内核检测到写端计数为 0,意味着“世界上再也没有人能往这个管道写数据了”。

  • 内核向读端发送EOF (End Of File)

  • 子进程的read函数收到 EOF,返回 0,循环结束,程序正常退出。

错误流程(忘记关闭 close)

  • fork后,写端引用计数 = 2。

  • 子进程没有关闭写端close(pipefd[1])

  • 父进程写完数据,关闭自己的写端 -> 写端引用计数降为 1(因为子进程手里还捏着一个写端 FD 呢!虽然它不用)。

  • 死锁时刻:子进程去read。因为写端计数是 1(不是 0),内核认为“还有人可能会写数据”,所以不发送 EOF。

  • 子进程一直傻傻地阻塞在read上,等待那个其实就在它自己手里的写端写入数据(但它自己由于阻塞在读上,永远不会去写)。

  • 程序挂起(Hang)。

这就是 Linux 进程间通信优雅而严谨的底层逻辑!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 1:17:38

Ubuntu 系统上安装和配置 Go 语言运行环境

Ubuntu 系统上安装和配置 Go 语言运行环境&#x1f680; 方法一&#xff1a;使用官方二进制包安装 (推荐) 这是 Go 官方推荐的方法&#xff0c;可以确保您获得最新版本。 步骤 1: 下载 Go 语言安装包 访问 Go 语言官方下载页面&#xff0c;找到适用于 Linux 的最新版本的压缩包…

作者头像 李华
网站建设 2026/5/4 3:38:08

AI测试、大模型测试(七)Java主流大模型框架技术

目录 一、大模型按「应用领域」分类 二、 主流框架技术特点 2.1 Spring AI框架 1、 pom依赖 2、 Spring AI特点 3、Spring AI 例子&#xff0c;Spring AI集成OpenAI并实现对话功能 2.2 LangChain4j框架 1、 LangChain4j简介 2、 LangChain4j使用 3、调用示例 一、大…

作者头像 李华
网站建设 2026/5/1 5:31:30

43、Linux系统故障排除与维护指南

Linux系统故障排除与维护指南 1. 文件系统挂载问题及解决 当文件包含无效条目时,文件系统将无法正确挂载。这种情况下,需要编辑 /etc/fstab 文件来修复错误。若根分区出现此问题,需手动挂载该分区,然后对文件进行修改。在启动过程中出现的任何错误消息都会记录在 /var…

作者头像 李华
网站建设 2026/5/1 12:42:25

“十五运”火炬手是机器人!它能自主奔跑背后的技术有多硬核?

万众瞩目的火炬传递现场&#xff0c;一位特殊的“运动员”稳步接过圣火&#xff0c;它不需要人类搀扶或遥控&#xff0c;便能自主识别路线、保持平衡、稳健奔跑——这并非科幻电影&#xff0c;而是全国第十五届运动会上的真实一幕。在2025年举办的第十五届全运会上&#xff0c;…

作者头像 李华
网站建设 2026/5/3 13:56:39

vscode中可以使用的免费的AI编程工具有哪些

VS Code 中有许多优秀的免费 AI 编程助手插件&#xff0c;以下是最受欢迎和实用的选择&#xff1a; &#x1f193; 完全免费&#xff08;无需付费&#xff09; 1. GitHub Copilot (有限免费) 免费条件&#xff1a;学生、教师、热门开源项目维护者个人免费&#xff1a;GitHub Co…

作者头像 李华
网站建设 2026/4/28 3:16:39

iOS 巨魔商店专属 VansonMod 神器!无需越狱改内存、管存档,越狱支持汇编 Patch,还能 Hex 编辑 + 进程管理,iOS14 + 适配~

&#x1f31f;简介 VansonMod 是一款专为 TrollStore&#xff08;巨魔商店&#xff09; 环境量身打造的全能型 Root 辅助工具。凭借创新的 外部运行机制&#xff0c;无需完整越狱即可实现游戏数值修改、应用存档管理等核心功能&#xff0c;更支持越狱环境下的汇编指令&#xff…

作者头像 李华