核心 02-进程线程与调度 预计 25 分钟 kp-009

进程间通信(IPC)总览

进程间通信(IPC,Inter-Process Communication)是操作系统为相互隔离的进程提供的数据交换与事件通知机制族,按"经过内核拷贝几次"与"是否需要同步"分为不同代价档位。

学习状态:

一句话定义

进程间通信(IPC,Inter-Process Communication)是操作系统为相互隔离的进程提供的数据交换与事件通知机制族,按"经过内核拷贝几次"与"是否需要同步"分为不同代价档位。

为什么重要

隔离(独立地址空间)与协作(交换数据)天然矛盾,IPC 就是这对矛盾的官方解法。微服务间的 RPC 底层是套接字,Shell 的管道是 Unix 哲学的化身,数据库的 WAL 与共享内存方案直接决定吞吐。选错 IPC 档位是很多"莫名慢"的根因。

前置知识

kp-005(进程隔离与文件描述符);kp-003(系统调用)。

核心概念

  • 匿名管道(pipe):单向字节流,仅限父子进程,Shell 的 | 即它。
  • 命名管道(FIFO):有名字的管道,无亲缘关系的进程可用。
  • 消息队列:内核维护的离散消息链表,有边界、可选优先级。
  • 共享内存(shm/memfd):同一块物理内存映射进多个进程,速度最快但需自行同步(配合 kp-013 信号量)。
  • 信号(signal):异步事件通知,带编号与默认动作,不是可靠的数据通道。
  • 套接字(socket):跨主机与本地(Unix domain socket)通吃的通用接口。

原理与机制

按代价与语义对比选型:

机制数据边界拷贝次数同步典型场景
管道无(字节流)2 次(用户到内核到用户)阻塞读写自带同步命令行组合
消息队列有(消息)2 次可选任务分发
共享内存无0 次(映射后直接访问)需信号量/锁自建高频大数据量
信号无0异步打断事件通知
Unix 套接字流或报文2有连接语义本机服务间 RPC

管道的实现要点:内核用环形缓冲页承载字节流,读端写端各持一个文件描述符;写端全部关闭后读端读到 EOF,这是 cat file | head 能优雅终止(SIGPIPE)的机制基础。

图示

共享内存路径:   进程A --映射--> [同一物理页] <--映射-- 进程B      (0 次拷贝, 需自配锁)
管道路径:       进程A --write--> [内核缓冲] --read--> 进程B      (2 次拷贝, 内核管同步)

直观类比

管道像食堂传菜口:单向、排队、口子关了就知道没菜了。共享内存像两家人共用同一个冰箱:放取最快,但必须自定规矩(锁)防止同时伸手。信号像火警铃:只能告诉你"有事",传递不了详细信息。

实例或案例

who | wc -l                     # 匿名管道:ps 的输出成为 wc 的输入
mkfifo /tmp/myfifo              # 命名管道实验:
( cat /tmp/myfifo & ) ; echo hello > /tmp/myfifo
strace -e trace=pipe,pipe2,read,write sh -c 'echo hi | cat'   # 观察 pipe2 与读写序列
ipcs -m                         # 查看系统共享内存段(System V 接口)

常见误区

  • 认为共享内存自动同步:它只提供内存,读写并发保护必须自己加锁或信号量。
  • 把信号当可靠队列:同类未决信号会合并,处理函数里还只能用异步信号安全函数。
  • 忽略 SIGPIPE:向已关闭的管道写会触发默认终止进程,网络服务必须显式忽略并处理 EPIPE。

与其他知识点的关系

管道与套接字的阻塞/非阻塞语义延伸到 kp-028 的 I/O 多路复用;共享内存的同步问题正是 kp-012、kp-013 的应用场景。

延伸阅读

《UNIX 环境高级编程》(APUE)第 15、16 章;man 7 pipe、man 7 sigevent。

自测题

  1. 为什么共享内存最快却不能到处用?

答:它省掉了内核拷贝,但同步责任完全交给应用,稍有不慎就引入竞态;低频小数据用管道或套接字更简单可靠。

  1. Shell 管道 a | b 中,a 退出后 b 如何知道数据结束?

答:a 的写端描述符随进程退出被关闭,b 读到 EOF(read 返回 0),这就是字节流的结束信号。

  1. 信号与消息队列最本质的差别?

答:信号是异步通知(无数据边界、会合并、打断执行流),消息队列是同步读取的数据通道(消息有边界、按序排队)。

标签:#IPC #管道 #共享内存 #信号 #套接字