Skip to content

进程间通信

2026 大纲 二(一)5 进程间通信,补充说明点名共享内存、消息传递、管道、信号四种方式。

两个进程被隔开了,那它们怎么说话

前面几节一直在强调进程之间是隔开的:各有各的地址空间、 各有各的 PCB、一个进程改不了另一个进程的内存。这是保护的基础。

可实际系统里进程又必须协作——浏览器的渲染进程要把画面交给合成进程, ls 的输出要交给 grep隔离是前提,通信是需求,两者天生冲突。

解决办法只有一条路:由内核在中间开一个受控的口子。 而口子怎么开,决定了四种方式的全部性质:

共享存储——内核把同一批物理页框映射进两个进程的页表, 之后内核就退出数据通路了,两边直接读写内存。 这一条同时解释了它最快(没有任何拷贝、没有系统调用) 和它必须自己外挂信号量做互斥(内核根本不知道谁在写)。

消息传递——数据打包成消息,send/receive 走内核中转。 内核在通路上,所以同步由它顺带处理了,代价是要拷贝、要陷入内核。

管道——本质是内核里的一个固定大小缓冲区,自带同步(满则写阻塞、 空则读阻塞),但不自带互斥(多个写者仍会乱)。

信号——它压根不传数据,只传"发生了某件事"这个事实。 用位向量记录,因而不计数、不排队、可能丢失

所以选型判据不是"哪个最快",而是三问:传数据还是传事件? 数据量多大、传多少次?跨不跨机器?

一、共享存储(共享内存)

建立过程:双方通信前先向系统申请共享存储区中的一个分区 → 各自把它附加(映射)到自己的地址空间(页式系统里就是把同一批物理页框填进两个进程的页表,双方用各自不同的逻辑地址经各自页表变换后落到同一批页框上,见 页式管理)→ 此后像读写普通内存一样读写 → 用完把分区归还。

形式共享区里放什么谁负责同步层次
基于数据结构的共享特定格式的数据结构(如有界缓冲区)程序员自己低级通信,只适于传递相对少量的数据,效率低下
基于存储区的共享任意数据,形式和位置由进程自己决定进程自己高级通信,为传输大量数据而设

两者的差别在于是谁规定了共享区里的格式:OS 规定的是前者(所以受限),进程自己说了算的是后者。

二、消息传递

格式化的消息为单位传递数据。消息由消息头(发送进程标识、接收进程标识、消息类型、消息长度等控制信息,长度固定)与消息体(真正要传的数据)组成。

消息格式优点代价适用
定长处理和存储开销小长消息要拆成多条单机系统内、发送与接收进程环境相同时;便笺式的短通信
变长方便用户,长消息不必拆系统在处理和存储两方面都要付出更多开销需要发送较长消息时

直接通信在原语里直接指明对方进程。收发双方都指名道姓的叫对称寻址,它的不足是某进程改名后所有引用过这个名字的定义都得跟着改;接收方不指定发送者、只用一个返回参数带回源进程的叫非对称寻址,打印服务这类"要接收任意进程请求"的场合必须用它。

send(B, message)     // 对称寻址:进程 A 向进程 B 发送消息
receive(A, message)
send(P, message)     // 非对称寻址:接收任意进程的消息
receive(id, message) // id 返回实际发送方

间接通信(信箱通信)让消息经信箱中转,双方都不必知道对方是谁。信箱分信箱头(信箱标识符、拥有者、口令、空格数等描述信息)与信箱体(若干信箱格,格数与每格大小在创建信箱时确定)。"信箱头里有空格数"意味着信箱容量有限,满了就发不进去——这正是链路容量的具体形式。

链路属性两种取值判据/后果
怎么建链显式建链:发送进程用"建立连接"原语请求系统建链,用完拆除
隐式建链:不必提出请求,系统在它发出 send 时自动建链
显式主要用于计算机网络,隐式主要用于单机系统
方向单向链路 / 双向链路决定要不要建两条链路
容量无容量 / 有容量(可暂存 n 条)直接决定 send 会不会阻塞
send / receive 组合行为什么场合用
发送阻塞 + 接收阻塞双方都停下来会合进程之间紧密同步、收发之间无缓冲(无容量链路)时
发送不阻塞 + 接收阻塞发送方投出去就走;接收方平时阻塞着,来消息才被唤醒应用最广,服务器等待请求就是这个形态
发送不阻塞 + 接收不阻塞双方各忙各的,仅当某事件让它无法继续时才阻塞自己也较常见

第四种组合(发送阻塞 + 接收不阻塞)很少用:接收方不阻塞意味着它得反复轮询,发送方却停下来等,两头的设计意图互相矛盾。

三、管道通信

管道是用于连接一个读进程和一个写进程的一个共享文件(又名 pipe 文件),实体是内存中一个固定大小的环形缓冲区。写进程以字符流形式送入数据,读进程从中读出。

进程A(写入) ───► 【管道缓冲区】───► 进程B(读取)
             写端                  读端
必须提供的协调能力具体做什么为什么必须有
互斥一个进程正在对 pipe 执行读/写时,其他进程必须等待环形缓冲区的读写指针是共享变量,并发改动会错乱
同步写进程写入一定数量数据后便睡眠等待,直到读进程取走才被唤醒;读进程读空 pipe 时也睡眠等待,直到写进程写入才被唤醒缓冲区容量有限,两端速度不匹配时必须有一方停下来
确定对方是否存在只有确定了对方已存在,才能进行通信对面没人时继续读/写没有意义,必须给出确定的行为
匿名管道(无名管道)命名管道(FIFO)
有没有文件名没有,在文件系统中没有路径有,在文件系统中有一个路径名
双方怎么找到它只能靠继承:创建管道后 fork,子进程继承父进程打开的文件描述符双方各自按路径名打开即可
适用范围只能用于有亲缘关系的进程(父子、兄弟)任意两个进程,互不相识也可以
生存期随最后一个持有它的进程结束而消失文件本身持久存在,直到被显式删除

四、信号

信号是一种用于通知进程某个事件已发生的异步通信机制。每种系统事件对应不同的信号类型,每类信号有一个序号。进程 PCB 中用一个 n 位向量记录当前待处理的信号(某位为 1 即待处理,处理后清零),另一个 n 位向量记录被阻塞(屏蔽)的信号——被阻塞的信号暂存,直到解除阻塞才处理。

发送有两条来源:内核检测到系统事件时发送(执行非法指令 → SIGILL;向读端已关闭的管道写 → SIGPIPE),或进程调用 kill() 向指定 PID 发送。处理分三种:默认处理(执行 OS 预设操作,如 SIGILL 默认终止进程)、自定义处理(进程为某类信号注册处理函数)、忽略。处理程序执行结束后通常返回原程序被中断的位置继续执行。

信号为什么被称为"软中断":与硬件中断逐项对照(想弄清这个别名的分寸时展开)
硬件中断信号
由谁触发外设或 CPU 内部异常内核检测到系统事件,或另一进程调用 kill()
打断谁打断处理机当前的指令流打断进程的正常执行流
谁来处理中断处理程序(内核态)信号处理程序(多在用户态执行)
能不能屏蔽可用中断屏蔽字屏蔽可用信号屏蔽向量阻塞
处理完去哪返回被中断的断点通常返回原程序被中断的位置继续执行

两者的层次并不相同:硬件中断是处理机级的机制,由硬件递交;信号是进程级的机制,由内核在合适的时机递交给进程。硬件中断的细节见 中断和异常的处理

五、四种方式的对比与选型

方式数据通路速度(及依据)内核开销适用数据量同步机制方向
共享存储双方页表指向同一批物理页框,数据不经内核最快零数据拷贝、零系统调用,通信时就是普通访存建立映射时一次性开销,之后为零,且传输次数越多越划算须自行处理(信号量等)双向
消息传递数据经内核缓冲区中转中等:每条消息 2 次拷贝(发送方→内核,内核→接收方)+ 收发各一次系统调用每条消息都有,与消息条数成正比中小,或跨机器无容量+双阻塞时由 OS 保证会合;其余情形仍需自理双向
管道数据经内核中的环形缓冲区中等:同样是 2 次拷贝,但接口是字节流,无消息头开销每次读写都有中等,流式数据自动同步(满写阻塞、空读阻塞),但多读/多写仍需互斥半双工
信号只改 PCB 里的一位快,但不传数据极小不传数据(只有一个信号编号)异步通知,不排队、可能丢失单向
把"数据量与次数才是判据"算成具体数字:共享存储什么时候反而最慢(想给选型三问里的第②问一个量化标准时展开)

设内存拷贝速率 2 GB/s,一次系统调用 1 µs,一对 P/V 操作 1 µs,建立一次共享内存映射的一次性开销 200 µs。消息传递需 2 次数据拷贝 + 2 次系统调用;共享存储需 1 次数据拷贝(写方写入共享区,读方直接读)+ 一对 P/V。

第一步,把"一次拷贝"折算成时间,这是全篇推算的基本单位:

t拷贝(1MB)=106 B2×109 B/s=500 μs

第二步,按各自真正发生的动作逐笔组装单次开销(不能笼统地说"消息传递慢一倍"):

t消息=2×500两次拷贝+2×1两次系统调用=1002 μst共享=1×500一次拷贝+1一对 P/V=501 μs(另有一次性映射开销 200 μs)

第三步,传 100 条 1 MB 数据(映射开销只算一次,这正是"一次性"的含义):消息传递 1002×100=100.2 ms,共享存储 200+501×100=50.3 ms,降幅 49.8%。省下来的正好是那一次多余的拷贝——1 MB 量级下两次系统调用的 2 µs 完全可以忽略。

第四步,换成 4 字节的控制信息,拷贝时间降为 0.002 μs 几乎为零,开销结构完全反转:

t消息=2×0.002+2=2.004 μs,t共享=0.002+1=1.002 μs

只传 1 次:消息传递 2.004 µs,共享存储 200+1.002=201.0 μs——共享存储反而慢 100 倍,那 200 µs 建映射开销无处摊薄。回本次数由"每次省下的 1.002 µs 什么时候攒够 200 µs"决定:

N=2002.0041.002199.6要传 200 次以上共享存储才划算

共享存储省的是拷贝,付的是建映射。 传一次几个字节的控制信息,用消息传递甚至信号远比开一块共享内存合算。

考点速记

  1. 共享存储把同一批物理页框映射进两个进程的页表,之后内核不在数据通路上——这一条同时解释了它最快和它必须自己外挂信号量做互斥
  2. ⚠️共享内存下"虚拟页号不一定相同,物理页框号一定相同":两个进程各自独立分配虚拟地址空间,同一块共享内存在它们的地址空间里可以落在不同位置;但共享的本质就是指向同一批物理页框,所以页框号必然相同。(与内存映射文件是同一条结论。)
  3. 消息传递的"同步由 OS 顺带处理"只在无容量 + 双阻塞时完整成立。
  4. 管道自带同步、不自带互斥满则写阻塞、空则读阻塞(所以读和写都可能被阻塞),但多个写者仍会互相干扰。
  5. 管道是半双工的——一个管道只能单向传输,要双向就得开两个。
  6. 管道的容量是内核里一块固定大小的缓冲区(通常几十 KB),⚠️不是"受磁盘容量限制"——它根本不在磁盘上。
  7. ⚠️一个管道可以有多个读进程或多个写进程(只是需要额外互斥),不是"只能一个"。
  8. "管道只能用于父子进程"仅对匿名管道成立,根因是它没有名字——只能靠 fork 时继承 fd 来传递;命名管道(FIFO)有路径名,任意进程都能打开。
  9. 信号位向量记录,因而不计数、不排队、可能丢失只传事件不传数据
  10. 选型判据是三问,不是"哪个最快":传数据还是传事件?数据量多大、传多少次跨不跨机器

这一节在真题里被考过的形式

ipc 这个标签下挂了 9 道题,但其中 6 道实际考的是信号量 (2010-25、2013-45、2015-45、2020-45、2021-45、2026-26), 在信号量与各经典同步问题里讲—— 本页下方练习区渲染的题比本节内容宽,属正常。真正落在本节的有两道:

  • 判断管道通信的四条叙述,选正确的(2014-31)。答进程对管道进行读操作和写操作都可能被阻塞(速记第四条)。⚠️ 另三项各错一处:"一个管道可实现双向数据传输"错——管道半双工,双向要开两个(第五条);"管道的容量仅受磁盘容量限制"错——它是内核里的一块固定大小缓冲区,跟磁盘无关(第六条);"一个管道只能有一个读进程或一个写进程"错——可以有多个,只是需要额外互斥(第七条)。这道题一题包了四个考点。
  • 两进程共享 data,问虚拟页号与物理页框号的关系(2023-30)。答页号不一定相等、页框号一定相等。⚠️ 判据就是速记第二条:虚拟地址由各进程独立分配、可以不同;共享的本质是同一批物理页框,所以框号必然相同。四个选项恰好把"两个都一定、两个都不一定、以及两种交叉"摆齐,只要抓住"共享共享的是物理内存"就不会选错。

复习优先级必须拿满,两道题各记一组判据。 管道那四条性质(半双工、 内核缓冲区、读写都可能阻塞、可多读多写)建议整组记住,2014-31 一题就考了四条。 第二条那个"虚拟页号不一定同、物理页框号一定同"在内存章已经出现过一次,是同一条结论。 第十条那三问的选型判据不会直接设问,但能防止"共享存储最快所以最好"这种误判。

易错:认为一个管道能双向传输。管道是半双工的,双向要开两个。

易错:认为管道容量受磁盘限制。它是内核里的一块固定大小缓冲区,不在磁盘上。

易错:认为管道只能一个读者一个写者。可以有多个,只是需要额外做互斥。

易错:认为只有写管道会阻塞。满则写阻塞、空则读阻塞,两边都会。

易错:认为共享内存下两个进程的虚拟地址一定相同。虚拟页号不一定同,物理页框号一定同

易错:认为共享存储自带互斥。内核退出了数据通路,互斥必须自己外挂信号量。

易错:认为信号可以传数据、且不会丢。它用位向量记录,不计数、不排队、可能丢失

易错:把"只能用于父子进程"套到所有管道上。只对匿名管道成立——它没有名字,只能靠继承 fd。

教材出处
  • 汤小丹《计算机操作系统》2.6 进程通信、2.6.1 进程通信的类型,印刷 p67–p68:低级通信的两条不足(效率低、对用户不透明)与高级通信的两条特点;四大类高级通信机制;共享存储器系统的两种类型;管道的定义(连接读写进程的共享文件,又名 pipe 文件)与必须提供的三种协调能力(互斥、同步、确定对方是否存在)
  • 汤小丹《计算机操作系统》2.6.2 消息传递通信的实现方式,印刷 p70–p71:对称寻址与非对称寻址;消息的格式(定长与变长的取舍);进程同步方式的三种阻塞组合;通信链路的两种建立方式与单向/双向之分
  • 汤小丹《计算机操作系统》2.6.2 信箱通信,印刷 p71:信箱的结构——信箱头(含信箱标识符、拥有者、口令、空格数)与信箱体(若干信箱格,格数与格大小创建时确定)

相关知识

进程的组织与控制信号量与 PV 操作内存映射文件中断和异常的处理调度的基本概念与目标

真题练习