Skip to content

入门:为何需要 IPC 与各机制概览

基于通用操作系统概念 · 核于 2026-08

速查

  • 为何需要 IPC:进程各自有独立虚拟地址空间,A 进程的指针在 B 进程里无效——要交换数据,必须经 OS 提供"受控通道",这就是 IPC。
  • 两大分类:①数据传递(管道/消息队列/套接字,OS 代为搬运字节或消息);②共享存储(共享内存,双方映射同一物理页,直接读写)。
  • 匿名管道(pipe)pipe() 创建一对 fd,父子进程间用,半双工,字节流,随进程消亡。
  • 命名管道(FIFO):文件系统里有路径名,任意进程可 open,半双工,常用于无亲缘进程间。
  • 消息队列:内核维护的结构化消息链表,按类型收发,有边界(不像 pipe 的字节流)。
  • 共享内存(shm):最快的 IPC——双方映射同一物理页,零拷贝,但必须配信号量同步(否则竞态)。
  • 信号量(semaphore):本身不传数据,只做同步/互斥计数器,常与共享内存配对。
  • 信号(signal)异步通知机制,内核/进程向目标发软件中断(SIGINT/SIGKILL/SIGCHLD),只能传信号编号不能传数据(sigqueue 例外)。
  • 套接字(socket):最通用的 IPC,既可本机(UNIX domain socket)也可跨机(TCP/UDP),是网络通信的基础。
  • RPC(远程过程调用):让跨机调用像本地函数,靠 stub 序列化参数 + 网络传输,隐藏网络细节。
  • 速度排序(单机):共享内存 > 消息队列 ≈ 管道 > 套接字。共享内存最快(无内核拷贝),套接字最慢(协议栈开销)。
  • 同步 vs 异步:管道/消息队列读写默认阻塞(同步);信号是异步中断;socket 可设非阻塞/IO 多路复用做异步。
  • 范围:pipe/FIFO/shm/sem 只能本机;socket/RPC 可跨机

一、为何需要 IPC:进程地址空间隔离

OS 给每个进程分配了独立的虚拟地址空间——进程 A 看到的地址 0x4000 与进程 B 的 0x4000 映射到不同的物理页,两者互不可见。这种隔离是保护的基石(A 的 bug 不能 corrupt B 的内存),但也带来一个问题:进程之间无法直接交换数据

进程 A 的地址空间          进程 B 的地址空间
┌──────────────┐          ┌──────────────┐
│ 0x4000: "hi" │          │ 0x4000: ???  │  ← A 的指针传给 B 无效
│ ...          │          │ ...          │
└──────────────┘          └──────────────┘
        ↑                          ↑
        └──── 要交换数据 ────┘
              必须经过 OS 提供的 IPC 通道

任何进程间数据交换都必须借助 OS 提供的机制——要么让 OS 代为搬运(管道/消息队列/套接字),要么让 OS 划一块双方都能访问的内存(共享内存)。这就是 IPC 存在的根本原因。

二、通信两大类:数据传递 vs 共享存储

IPC 机制按"数据怎么从 A 到 B"分成两大类:

类别机制数据如何流动代表
数据传递管道、消息队列、套接字A 调用 write,OS 把数据从 A 的地址空间拷到内核缓冲,B 调用 read 再从内核拷到自己shell 管道 |、socket
共享存储共享内存OS 让 A、B 映射同一物理页,双方直接读写同一块内存,无拷贝X11 共享内存、数据库缓冲
  • 数据传递的好处是 OS 代管边界与同步(管道写满阻塞、消息队列按类型取),安全简单;代价是每次通信有内核拷贝开销。
  • 共享存储的好处是零拷贝、最快(大块数据如视频帧传输首选);代价是没有同步——A 和 B 同时读写同一地址会竞态,必须额外配信号量协调。

三、各机制概览

管道(pipe / FIFO)

最经典的 IPC。匿名管道由 pipe() 创建,返回读/写两个 fd,只能在有亲缘关系(父子)的进程间用(通过 fork 继承)。命名管道(FIFO)是文件系统里的一条特殊文件(mkfifo),任意进程都能 open 它通信。管道是半双工(单向)字节流,有内核缓冲(Linux 默认 64KB)。

消息队列

内核维护的链表,每条消息有类型内容,发送方 msgsnd、接收方 msgrcv 可以按类型筛选。相比管道的字节流,消息队列保留消息边界,且无亲缘限制。System V 和 POSIX 各有一套。

共享内存

最快 IPC。shmget/mmap 让多个进程把同一块物理内存映射进各自的虚拟地址空间,之后读写就是普通内存访问,不经内核。代价是必须配信号量同步。

信号量(semaphore)

本身不传数据,是同步原语——一个非负计数器,P(wait)减、V(post)加。用于保护临界区,几乎总是和共享内存配对出现。

信号(signal)

异步通知机制。内核或进程用 kill(pid, sig) 给目标进程发信号(如 SIGINT=Ctrl+C、SIGKILL=强杀、SIGCHLD=子进程退出),目标进程的执行被中断,跳到信号处理函数。信号只能传编号(sigqueue 可带一个整数),不适合传大量数据。

套接字(socket)

最通用的 IPC。socket() 创建一个通信端点,既可用于本机(UNIX domain socket,文件路径寻址,比 TCP 快)也可用于跨机(TCP/UDP,IP+端口寻址)。是网络编程的基础,所有 HTTP/RPC/WebSocket 都跑在 socket 上。

RPC(远程过程调用)

跨机通信的高层抽象——让调用远程机器上的函数像调用本地函数一样。客户端调 stub,stub 把参数序列化通过网络发给服务端,服务端 stub 反序列化后执行真正函数,再把结果传回。隐藏了网络的复杂性。

四、速度与范围对比

机制单机速度跨机同步典型场景
共享内存最快(零拷贝)需自配信号量大数据/视频帧、数据库
消息队列内核管边界任务分发、结构化消息
管道/FIFO内核管阻塞shell 管道、父子通信
信号量本身即同步保护共享内存临界区
信号极快部分(kill 跨进程)异步中断通知/控制(Ctrl+C)
套接字慢(协议栈)可阻塞/非阻塞网络通信、跨机
RPC慢(序列化+网络)同步调用为主微服务、分布式

一句话选型:单机大数据要快 → 共享内存;单机有结构/边界 → 消息队列;shell 串命令 → 管道;跨机 → 套接字/RPC;只需通知 → 信号。

下一步

理解了 IPC 的全景与分类后,下一步深入两条主线——管道、消息队列与套接字(数据传递类机制的字节流/消息边界/网络能力)与共享内存与 RPC(最快 IPC 的同步配对、跨机透明调用、各机制对比表)。