跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

Linux 进程间通信:匿名管道详解

综述由AI生成Linux 进程间通信通过共享资源实现。匿名管道是 Unix 最古老的通信方式,基于单向字节流。使用 pipe() 接口创建内存缓冲区,配合 fork() 建立父子进程关系。管道具有固定大小(通常 64KB),支持原子写入(4KB)。读写端阻塞机制保证数据同步,读空写满时阻塞,读端关闭返回 0。典型应用如 shell 命令管道。代码示例展示了父进程读取、子进程写入的完整流程及资源清理。

奶糖兔发布于 2026/2/5更新于 2026/6/22.6K 浏览
Linux 进程间通信:匿名管道详解

进程间通信背景

键盘、显示器等资源是单份的,不同进程要想通信,前提是能看到同一份资源。文件描述符机制允许不同进程控制相同的文件对象,管道也是一种特殊的文件。

图:进程通信示意图

两个进程都能控制相同的文件,通过文件描述符进行读写操作。

管道

管道定义

  • 管道是 Unix 最古老的通信方式
  • 把一个进程连接到另一个进程的数据流叫做管道

图:管道数据流示意

匿名管道

建立通信比较困难,因为进程具有独立性。我们需要在一个进程中创建文件,该进程可以对文件读写,如果再来一个进程也可以对该文件读写,就可以通信了。

如何创建另一个进程?使用 fork 系统调用。

此外,管道之所以叫管道,因为它是单向流通的,传送字节流,就像水龙头那般。我们会让一个进程只读取,一个进程只写入。

图:单向管道示意

按照上述文字表述,只要创建文件就可以通信,但是文件是建在硬盘上的,我们在硬盘上读写太慢了,关闭进程时文件也不会删除,所以有管道接口,建立在内存上,关闭进程时自动清理。

接口

图:pipe 函数接口

该函数会把文件描述符带出来,如果不手动打开任何文件,默认 pipefd[0] 为读端,pipefd[1] 为写端。若已打开其他文件,则文件描述符继续排序。

其中默认 pipefd[0] 用于读文件,pipefd[1] 用于写文件。

实现匿名管道
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include 


  std;

{
    string s = ;
     self = ();
     buffer[];
     number = ;
     () {
        buffer[] = ;
        (buffer, (buffer), , s.(), self, number);
        cout << buffer << endl;
        number++;
        (wrd, buffer, (buffer));
         (number > ) ;
        ();
    }
}

{
     buffer[] = {};
     () {
        buffer[] = ;
         n = (rrd, buffer, (buffer));
         (n > ) {
            buffer[n] = ;
            cout <<  <<  << () <<  << buffer << endl;
        }   (n == ) {
            cout <<  << endl;
            ;
        }  {
            ;
        }
    }
}

{
     pipefd[] = {};
     n = (pipefd);
     (n < ) {
         ;
    }
    cout <<  << pipefd[] <<  << pipefd[] << endl;
     id = fork();
     (id < ) {
        cout <<  << endl;
    }
     (id == ) {
        (pipefd[]);
        (pipefd[]);
        (pipefd[]);
        ();
    }
    (pipefd[]);
    (pipefd[]);
    (pipefd[]);
    ();
     pid = (id, , );
     (pid < ) {
        cout <<  << endl;
         ;
    }
     ;
}
<cstdio>
#include <string>
using
namespace
void Writer(int wrd)
"hello pipe"
pid_t
getpid
char
1024
int
0
while
true
0
0
snprintf
sizeof
"%s-%d-%d"
c_str
write
strlen
if
5
break
sleep
1
void Reader(int rrd)
char
1024
0
while
true
0
0
int
read
sizeof
if
0
0
"father get message"
"["
getpid
"]#:"
else
if
0
"read file done"
break
else
break
int main()
int
2
0
int
pipe
if
0
return
1
"pipe[0]:"
0
" pipe[1]:"
1
int
if
0
"fork error"
if
0
close
0
Writer
1
close
1
exit
0
close
1
Reader
0
close
0
sleep
5
int
waitpid
nullptr
0
if
0
"waitpid error"
return
3
return
0

解析:先让 pipe 创建内存级缓冲区,fork 创建子进程。如果是子进程,关闭读端,把写端给函数写入;如果是父进程,关闭写端,把读端给函数。进行通信,通信结束后,子进程退出,父进程回收子进程。

写入函数逻辑:buffer 置空,把数据打印到 buffer,向 wrd 中写入 buffer,每隔 1 秒写一次,写 6 次后退出。 读取函数逻辑:一直在读取,把数据读取到 buffer 中,再打印出 buffer。若没数据可读,read 返回 0。

管道属性和特征

管道是有大小的,怎么测?我们把读端关闭,疯狂的向管道 1 字节 1 字节写入,打印即可。

int number = 0;
while (true) {
    number++;
    char ch = 'c';
    write(wrd, &ch, 1);
    cout << number << endl;
}

读端 sleep 100 秒。

计算结果:65536 / 1024 = 64KB。所以 1 个管道大小通常为 64KB。

原子写入最大字节数为 4KB,即小于 4KB 的数据可以直接写入(更大数据需要分片),保证全部写入成功否则失败。这保证了不会与其他写入交叉冲突。

例如 A 进程写入 AAAA,B 进程写入 BBBB,若没有原子写入,可能会写进去 AAABBBAB,而有原子写入则为 AAAABBBB 或 BBBBAAAA。

管道 5 大特征:

  1. 匿名管道是具有血缘关系的进程通信
  2. 管道是单向通信
  3. 父子进程会协同,同步与互斥,保证了数据安全
  4. 管道面向字节流
  5. 管道基于文件描述符可以像操作文件一样操作管道,但管道不是磁盘文件,操作系统开辟了一块内核缓存区给管道用,而内核缓存区生命周期随进程

管道 4 种情况:

  1. 读写端正常,管道为空,则读端就要阻塞
  2. 读写端正常,管道满了,则写端就要阻塞
  3. 读端正常,写端关闭,则读端读到 0,说明读到文件末尾,不会阻塞
  4. 写端正常,读端关闭,说明出 bug,操作就要通过信号杀死写端进程

管道应用

我们之前学的 ps axj | head -1,| 就是管道,意思是左边写入,右边读取。

图:Shell 管道示意

图:进程树示意

图:父子进程关系

可以看到 3 个进程父进程都是一样的,是具有血缘关系的。

目录

  1. 进程间通信背景
  2. 管道
  3. 管道定义
  4. 匿名管道
  5. 接口
  6. 实现匿名管道
  7. 管道属性和特征
  8. 管道应用
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Amazon DocumentDB Serverless 架构特性与弹性扩缩容指南
  • apt-get update 和 upgrade 的区别
  • Linux 下 Java JAR 包后台运行与端口检查实战
  • 蓝桥杯 C/C++组备考:C++基础知识(上)
  • 分布式文件系统 HDFS 编程实践与常用命令详解
  • IntelliJ IDEA 中 Tomcat 控制台乱码解决方法
  • 2026年医疗AI的可信革命全栈实现(上)
  • 抖音小说推文项目操作流程:利用解压视频实现变现
  • 具身智能发展瓶颈:AI 数据生成的解决方案与趋势
  • Scan2CAD 教程:AI 驱动的扫描图像转 CAD 模型
  • OpenClaw 安全风险全解析:AI 助手部署中的权限与数据隐患
  • Python asyncio 完全指南
  • DeepSeek R1-Zero 为何比 R1 更值得关注:纯强化学习范式解析
  • IntelliJ IDEA 切换 JDK 版本完整教程
  • 基于 Python 的餐饮供应链管理系统设计与实现
  • Flutter 三方库 eth_sig_util 在鸿蒙端的适配指南
  • 解决 Java 编译报错:源发行版 17 需要目标发行版 17
  • CentOS 部署 Teemii 搭建私人漫画库
  • Web 安全实战:Training-WWW-Robots 题目解析与 Robots 协议原理
  • 基于 OpenHarmony 的 Flutter 智能家居应用开发实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online