【操作系统原理】进程间通信之管道


🎉博主首页: 有趣的中国人

🎉专栏首页: 操作系统原理

🎉其它专栏: C++初阶 | C++进阶 | 初阶数据结构


文章目录

  • 【操作系统原理】进程间通信:管道(pipe/FIFO)
    • [1. 为什么需要进程间通信(IPC)](#1. 为什么需要进程间通信(IPC))
    • [2. 进程为什么不能直接"互相读写内存"](#2. 进程为什么不能直接“互相读写内存”)
    • [3. IPC 方式总览](#3. IPC 方式总览)
      • [3.1 本地通信(同一台机器)](#3.1 本地通信(同一台机器))
      • [3.2 网络通信(跨机器)](#3.2 网络通信(跨机器))
    • [4. 匿名管道 pipe:是什么](#4. 匿名管道 pipe:是什么)
      • [4.1 pipe 的核心模型](#4.1 pipe 的核心模型)
      • [4.2 重要限制](#4.2 重要限制)
    • [5. 管道的 4 种关键情形(面试高频)](#5. 管道的 4 种关键情形(面试高频))
      • [5.1 管道为空 + 写端存在](#5.1 管道为空 + 写端存在)
      • [5.2 管道写满 + 读端存在](#5.2 管道写满 + 读端存在)
      • [5.3 写端全部关闭(read 读到 EOF)](#5.3 写端全部关闭(read 读到 EOF))
      • [5.4 读端全部关闭(Broken Pipe / SIGPIPE)](#5.4 读端全部关闭(Broken Pipe / SIGPIPE))
    • [6. 管道的 5 个重要特征(理解到内核视角)](#6. 管道的 5 个重要特征(理解到内核视角))
      • [6.1 只能在亲缘进程间使用(匿名 pipe)](#6.1 只能在亲缘进程间使用(匿名 pipe))
      • [6.2 内部自带同步机制(顺序性)](#6.2 内部自带同步机制(顺序性))
      • [6.3 生命周期随进程(匿名 pipe 的"匿名")](#6.3 生命周期随进程(匿名 pipe 的“匿名”))
      • [6.4 面向字节流:消息边界会丢失](#6.4 面向字节流:消息边界会丢失)
      • [6.5 半双工模型(特殊)](#6.5 半双工模型(特殊))
    • [7. 命名管道 FIFO:解决"无亲缘也要通信"](#7. 命名管道 FIFO:解决“无亲缘也要通信”)
    • [8. 管道在工程里的经典用法:进程池(Master-Worker)](#8. 管道在工程里的经典用法:进程池(Master-Worker))
      • [8.1 进程池做什么](#8.1 进程池做什么)
      • [8.2 常见结构](#8.2 常见结构)
      • [8.3 最容易踩的坑](#8.3 最容易踩的坑)
    • [9. pipe / FIFO / socket 怎么选(快速决策)](#9. pipe / FIFO / socket 怎么选(快速决策))
    • [10. 小结](#10. 小结)

【操作系统原理】进程间通信:管道(pipe/FIFO)

1. 为什么需要进程间通信(IPC)

进程是"资源分配的基本单位",各自有独立的虚拟地址空间,默认互不干扰。

但真实系统里经常需要:

  • 多进程协作完成同一件事(流水线、进程池、服务拆分)
  • 数据共享与传递(任务、日志、控制指令、结果)
  • 提高吞吐与响应(并行处理)

结论:进程需要协同 → 必须通信


2. 进程为什么不能直接"互相读写内存"

因为这会破坏隔离性与安全性,成本也非常高。

系统的折中方案是:

让不同进程去访问同一份 OS 管理的"共享资源"

例如:内核缓冲区、共享内存段、消息队列对象、文件对象......

也就是:IPC 的核心不是"直接互访内存",而是"借助 OS 提供的通信媒介"。


3. IPC 方式总览

从常见使用场景看,大致分为两类:

3.1 本地通信(同一台机器)

  • 匿名管道(pipe)
  • 命名管道(FIFO)
  • System V IPC:消息队列 / 共享内存 / 信号量
  • Unix Domain Socket(本地 socket)

3.2 网络通信(跨机器)

  • TCP/UDP socket(走协议栈、可跨主机)

4. 匿名管道 pipe:是什么

匿名管道是最经典的本地 IPC。

4.1 pipe 的核心模型

  • pipe 由内核维护一段缓冲区(常见实现为环形队列)
  • 通过两个文件描述符访问:
    • 读端 fd:从缓冲区取数据
    • 写端 fd:向缓冲区写数据

4.2 重要限制

  • 只能用于"有血缘关系"的进程(通常是 fork 出来的父子进程)
  • 典型场景:父进程写、子进程读(或反过来)
  • 管道天然偏向"单向通信"(要双向需要两根管道)

5. 管道的 4 种关键情形(面试高频)

下面所有行为都可以用一句话记住:
空则读等,满则写等;写端全关读到 0;读端全关写会炸。

5.1 管道为空 + 写端存在

  • 读进程 read:阻塞等待
  • 这就是典型的"生产者-消费者"

5.2 管道写满 + 读端存在

  • 写进程 write:阻塞等待
  • 直到读端读走部分数据腾出空间

5.3 写端全部关闭(read 读到 EOF)

  • 当所有写端 fd 都关闭后:
    • 读端 read 会返回 0(EOF)
  • 这也是为什么:必须 close 不用的写端
    否则读端永远不会得到"结束"信号,可能一直阻塞。

5.4 读端全部关闭(Broken Pipe / SIGPIPE)

  • 当所有读端 fd 都关闭后:
    • 写端 write 会触发 Broken Pipe
    • 默认会收到 SIGPIPE(很多程序因此直接被终止)
  • 工程上通常会:
    • 忽略/捕捉 SIGPIPE
    • 或者对 write 的返回值进行错误处理(EPIPE)

6. 管道的 5 个重要特征(理解到内核视角)

6.1 只能在亲缘进程间使用(匿名 pipe)

因为 pipe 的 fd 是通过 fork 继承过去的。

6.2 内部自带同步机制(顺序性)

  • 同一根 pipe 上的数据是"字节流"顺序进入、顺序读出
  • 多写者场景下,内核会保证一定的原子性(与 PIPE_BUF 有关)

6.3 生命周期随进程(匿名 pipe 的"匿名")

  • pipe 本身没有文件名
  • 当进程退出、fd 全部关闭后,内核对象就会被回收

6.4 面向字节流:消息边界会丢失

  • 写入两次 ≠ 读两次(读到的数据可能粘在一起,也可能被拆开)
  • 所以工程上必须做"应用层协议":
    • 定长包
    • 分隔符
    • length + payload(最常见)

6.5 半双工模型(特殊)

一根 pipe 更天然的使用方式是"单向",像对讲机:

同一时刻更适合一边说一边听的单向流动。


7. 命名管道 FIFO:解决"无亲缘也要通信"

匿名 pipe 只能亲缘进程用,FIFO 用"文件名"把管道暴露出来:

  • FIFO 在文件系统里有一个名字(路径)
  • 无亲缘关系的进程也能通过这个路径打开同一条管道进行通信
  • 依然是:内核缓冲区 + 读写 fd(本质不变)

适用:同机上的两个独立程序(例如:日志采集器 ↔ 业务进程)。


8. 管道在工程里的经典用法:进程池(Master-Worker)

8.1 进程池做什么

  • Master:负责接收任务、分发任务、负载均衡
  • Worker:负责执行任务、返回结果(可选)

8.2 常见结构

  • Master 与每个 Worker 建立一条(或两条)管道
  • Master 端只保留写端,Worker 端只保留读端(其余全 close)
  • 分发策略:
    • 轮询(round-robin)
    • 最短队列(按繁忙度)
    • 哈希分桶(同类任务固定 worker)

8.3 最容易踩的坑

  • 忘记关闭无用端 → read 永远不返回 0 / write 触发 SIGPIPE 行为不清晰
  • 不做消息边界协议 → "粘包/拆包"导致任务解析错乱
  • 不处理 worker 退出 → master 写入触发 broken pipe

9. pipe / FIFO / socket 怎么选(快速决策)

  • 只在本机、亲缘进程:pipe(简单直接)
  • 本机、无亲缘:FIFO 或 Unix Domain Socket
  • 跨机器:TCP/UDP socket
  • 大块数据共享、追求极致性能:共享内存 + 信号量(或 futex 等)

10. 小结

  • IPC 的本质:借助 OS 提供的共享媒介
  • pipe/FIFO:内核缓冲区 + fd 读写 + 阻塞语义
  • 面试 4 情形必须背到"条件反射"
  • 工程落地一定要做:关闭无用端 + 应用层协议 + 异常处理
相关推荐
zyu672 小时前
03-Docker存储和网络
网络·docker·容器
Arciab3 小时前
51单片机_LCD1602液晶显示
网络·嵌入式硬件·51单片机
DX_水位流量监测4 小时前
大坝安全监测之渗流渗压位移监测设备技术解析
大数据·运维·服务器·网络·人工智能·安全
电商API&Tina4 小时前
京东 API 数据采集接口接入与行业分析
运维·服务器·网络·数据库·django·php
童话的守望者5 小时前
dc8靶场通关
网络
寂寞恋上夜5 小时前
异步任务怎么设计:轮询/WebSocket/回调(附PRD写法)
网络·人工智能·websocket·网络协议·markdown转xmind·deepseek思维导图
Tao____5 小时前
基于Ruoyi开发的IOT物联网平台
java·网络·物联网·mqtt·网络协议
chao_6666667 小时前
解决 PowerShell 中文乱码问题
网络·学习·powershell
喵了meme7 小时前
Linux学习日记24:Linux网络编程基础
linux·网络·学习
Yan-英杰7 小时前
BoostKit OmniAdaptor 源码深度解析
网络·人工智能·网络协议·tcp/ip·http