操作系统笔记-2.1.5.1 进程通讯
·
王道操作系统笔记,视频链接:2.1.5.1 进程通讯
知识总览
进程通讯的三种方式:
- 共享存储:
- 基于数据结构的共享
- 基于存储区的共享
- 消息传递:
- 直接通信的方式
- 间接通信的方式
- 管道通信
进程通信
进程通信定义
进程间通信(Inter-Process Communication, IPC)是指两个进程之间产生数据交互。
比如:微博文案转发分享到微信
为什么进程通信需要操作系统支持
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
PS:为了保证安全,一个进程不能直接访问另一个进程的地址空间。
共享存储
- 原理:如果操作系统支持共享存储的功能,一个进程可以申请一块共享存储区,这部分的内容也可以让其它进程共享。
- 比如:进程P要给进程Q传递信息,可以在共享存储区写入需要传递的信息,然后Q再从共享存储区读出数据即可。
- 举例:Linux中,可以通过 shm_open 系统调用,申请一片共享内存区,通过 mmap 系统调用,将共享内存区映射到进程自己的地址空间(虚拟地址空间,第三章会讲,也就是通过“增加页表项/段表项”将同一片共享内存区映射到各个进程的地址空间中)。
- 为避免出错(类似同时写入同一片区域这种错误),各个进程对共享空间的访问应该是互斥的。各个进程可使用操作系统内核提供的同步互斥工具(如P、V操作,这在2.3小节会讲解)。
- 基于存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
- 基于数据结构的共享;比如共享空间里只能放一个长度为10的数组(可以当成特殊的全局变量)。这种共享方式速度慢、限制多,是一种低级通信方式。
PS:为什么会慢?(来自deepseek)基于存储区是“放之四海而皆准”的,进程1可以随便放任意大小的结构体,进程2直接拿。而数据结构被卡死为“固定长度数组”。如果进程1的输出是 20 个字节,而数组每个元素只能存 8 字节,你就得手动拆分成 3 个元素存进去,进程2再拼回来。一旦涉及手动拆分拼接,就会多出额外的CPU运算和内存复制,这才变慢。
消息传递
- 原理:进程间的数据交换以格式化的消息(Message)为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
- 这里的格式化的消息由消息头与消息体构成,消息头包括:发送进程ID、接受进程ID、消息长度等格式化的信息。消息体保存的就是一个进程要传给另一个进程的数据。
- 消息传递分为直接通信方式与间接通信方式两种,前者消息发送进程要指明接收进程的ID,后者通过“信箱”间接地通信。因此又称“信箱通信方式”。
- 直接通信方式:
- 举例:
- 在进程Q的PCB中,包含有一个进程Q的消息队列,其它进程要给进程Q发送消息,都会挂在进程Q的消息队列中。
- 假设进程P希望发送一个消息给Q,P先在自己的地址空间完善生成一条格式化的消息msg,然后使用发送原语,send(Q,msg)将消息传递给操作系统内核,内核接收到这个消息,然后将这个消息挂在进程Q的消息队列中。也就是这个msg是由进程P的地址空间复制到内核空间的。
- 进程Q可以使用接收原语,receive(P,msg),进程Q执行接收原语后,操作系统检查进程Q的消息队列,然后将对应的消息从操作系统内核区复制到进程Q的地址空间。
- 直接通信方式需要点名道姓的消息传递,无论是发送还是接收都要指明对象。
- 间接通信方式
- 举例:
- 以进程P给进程Q发送信息为例,进程P利用系统调用,向操作系统申请一个或多个新的“邮箱”,并在自己的地址空间生成完善msg,然后调用发送原语,send(A,msg)往信箱A发送消息msg,此处没有指明某个特定的进程,只指明了哪个邮箱,所以算是间接通信。
- 进程Q使用接收原语指明邮箱,receive(A,&msg),从信箱A接受消息。
- 可以多个进程往同一个信箱send详细,也可以多个进程从同一个信箱中receive消息。
- 间接通信方式以“邮箱”作为中间实体进行消息传递。
- PS:两者区别(来自deepseek):
- 直接通信 = 微信私聊(你必须加对方好友(知道PID),消息只在你俩之间传输,离线就收不到)。
- 间接通信 = 朋友圈/公告栏(你只管发动态(塞邮箱),谁爱看谁看,谁爱评论谁评论,发的人不指定给谁,看的人也不在乎是谁发的)。
管道通信
如图:
- 定义:管道通信的方向与水管一样是单向的,这里的“管道”是一个特殊的共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存缓冲区。读写文件遵循先进先出原则,可以当作一个巨大的循环队列。
- 与基于存储区的共享存储的区别:共享存储从哪里写入、从哪里读取都没有限制,而管道通讯要求数据的读写都是先进先出。
- 管道只能采用半双工通信,某一时间段内只能实现单向的传输(传输完毕后可以更改传输的方向,但是同一时刻只能一个方向传输)。如果要实现双向同时通信,则需要设置两个管道。
PS:同一时刻支持双向的传输,叫做全双工通信,这是计网的概念。 - 各进程要互斥地访问管道(由操作系统实现)
- 当管道写满时,写进程将阻塞,直到读进程将管道中地数据取走,即可唤醒写进程。
- 当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
- 管道中的数据一旦被读出,就彻底消失。因此,当读个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:
- 一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案)
- 允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux方案)
- PS:这两个解决方案存在争议,在应试角度以“多个写进程,一个读进程”为准,但是现实角度来说“多个写进程,多个读进程”也完全没有问题。
知识回顾与重要考点

注意:
- 写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据
- 读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)