操作系统是如何一步步发明进程间通信的?


操作系统是如何一步步发明进程间通信的?

仅用于站内搜索,没有排版格式,具体信息请跳转上方微信公众号内链接

作为1970年代贝尔实验室的系统工程师,你亲历了操作系统的早期发展。当时,你刚刚实现了进程隔离机制,这是一项重大突破——每个进程都拥有自己独立的地址空间,彼此之间不会相互干扰。
进程真的是一个很棒的概念,快速在程序员之间流行起来,随着进程的大量使用,你很快发现了一个新问题:进程之间无法方便地交换数据。
这难不倒你们团队中的大聪明,小意思,可以直接借助磁带实现多个进程协同工作,假设有3个进程协同工作:
尽管这个方法可行但效率极低:
每次进程通信都需要完整的磁带I/O操作
进程之间无法实时通信,必须等待前一个进程运行完成
显然需要一种比大聪明的方法更聪明的进程间通信机制。
你知道大聪明的方法尽管不怎么聪明但思路是对的,不过为什么要借助磁带这种慢速设备而不是更快的内存呢?你突然想到:”如果能创建一个内存中的先进先出队列,让一个进程写入数据,另一个进程读取数据,不就解决问题了吗?这很像一个管道pipe”
你很快实现了第一个原型:
这个简单的设计解决了几个关键问题:
数据直接在内存中传递,避免了低俗磁带,速度杠杠的
为了实现以及使用起来更简单,你基于文件描述符进行管道读写,因为父子进程可以共享文件描述符,但这也限制了管道只能在父子进程之间使用
管道这个概念真的是太好用了,它快速流行起来,你的大名开始突破贝尔实验室的小圈子,管道极大提升了进程间通信的效率,并成为操作系统中最基础、最常用的IPC(进程间通信)机制之一。
随着管道的大量使用,管道的局限性很快就显现了:
管道只能用于有亲缘关系的进程(如父子进程)之间通信,这是你当初偷懒的结果
管道是单向的,双向通信需要创建两个管道
管道中的数据是无结构的字节流,缺乏消息边界
如何让没有亲缘关系的进程之间通信?这些限制促使你继续探索更强大的IPC机制。
这时大聪明的思路又一次在你的脑海中浮现了出来,磁带数据这种东西天然可以突破进程亲缘关系,因为文件并不限于某个进程的读写,如果能给管道一个名字,并将其注册到文件系统中,那么任何进程都可以通过这个名字来访问管道。
啊哈,你真的是比大聪明聪明大了。
既然管道有名字了,那么这个新管道就叫命名管道(NamedPipe)。
命名管道的实现非常成功,它让任意两个进程都能通过文件系统路径建立通信。这种方式有几个显著优点:
突破了传统管道只能用于亲缘进程的限制
复用了文件系统的权限管理机制
使用文件I/O接口,对程序员友好
你的名声又一次在计算机科学届出圈,实现了二次出道,属于你的时代又一次到来了,命名管道开始大量使用起来。
然而,随着应用场景的复杂化,命名管道也开始显露出一些不足:
仍然是单向通信,双向通信需要创建两个FIFO
缺乏消息边界,处理变长消息比较麻烦
没有内置的多客户端支持机制
这促使你设计了一种新的IPC机制:消息队列。与管道不同,消息队列:
支持结构化的消息,每条消息有明确的边界
可以为消息分配优先级
支持按类型接收消息,而不仅仅是FIFO顺序
你的实现大致如下:
消息队列的引入极大地简化了复杂系统中的进程通信。特别是在处理多种类型消息的场景下,它的优势非常明显。
然而,随着这种进程间通信机制的使用问题又一次暴露了出来。
你发明的这些通信机制,如管道、消息队列等需要将数据从用户空间拷贝到内核缓冲区,再拷贝到接收进程的用户空间。两次数据拷贝(用户态到内核态再到用户)增加了CPU和内存的开销。
图像处理、科学计算、数据库系统等应用需要进程间频繁交换大量数据。传统IPC的延迟和吞吐量难以满足这些场景的实时性要求。
这些通信机制要求数据以固定格式序列化传输,复杂数据结构(如链表、树)的传递需要额外序列化/反序列化步骤,增加开发复杂性和性能损耗。
为什么进程之间通信会有这些问题呢?你不禁陷入思考,这让你不得不追溯到进程发明的起点,未完待续。。。
推荐一下我写的专栏《深入理解操作系统》,第二版焕新升级,600+精美手绘图、87节精讲,如果你对操作系统感兴趣并且喜欢这篇文章的风格,那么这个专栏就是为你准备的:
操作系统是如何一步步发明进程、线程的?
操作系统是如何一步步发明中断机制的?
操作系统是如何一步步发明系统调用的?


文章作者: ZejunCao
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ZejunCao !
  目录