Why?
为什么需要 IPC?信息共享、加速计算(利用多核 CPU)、模块化(不同进程各司其职)。
Chrome 的多进程例子:
- 浏览器(单一进程):负责磁盘和网络 I/O,管理渲染进程
- 渲染进程(rendere processes,多进程):每个页面一个进程,处理 HTML、CSS、图片,运行 JS 等。一个页面有 bug 不影响其他页面
- 插件进程(每个插件一个进程)
浏览器进程与渲染进程、插件进程通过 IPC 沟通。渲染进程放在沙箱运行,减少安全风险(无法访问磁盘等)。
How?
主要有两种形式:
- 靠内存共享:比如 Linux 的共享内存。性能好,使用的系统调用少,但难以分布到多机
- 靠通讯(message-passing)共享:比如 Linux 的消息队列,或者通过网络进行的通讯。性能相对差,但是可以分布到多机
基础模型:生产者与消费者:
- 生产者产生数据,存放在 buffer 中供消费者消费;Buffer 可以指共享的内存区域,可以指消息队列等
- Buffer 分为不限大小的 unbounded buffer,以及限制大小的 bounded buffer
消息传递(message-passing)系统的设计
角色:进程 P,进程 Q,及它们之间的通讯链路(communication link)。
逻辑上需要实现两个操作:send()
/ receive()
。关心的元素有:
- 直接或间接地沟通
- 同步或异步的沟通
- 不同容量的 buffer
直接 / 间接
直接通讯:
send(P, message)
:发送一个消息到进程 Preceive(Q, message)
:接收一个进程 Q 发来的消息
这要求 对称的寻址(symmetry in addressing),即 Q 发给 P 时需要指明 P,P 收 Q 消息时需要指明 Q。不灵活。改进方式是使其变成 非对称的(asymmetry),即 P 收消息时不需要指定发送方,而是在消息中包含了发送方信息。
更好的方法是 间接通讯。给定一个邮箱 A,让收方双方都对邮箱做操作:
send(A, message)
receive(Q, message)
还有一些细节,需要具体的实现方式去权衡。比如是否可以多个进程收取同个消息。
邮箱可以被一个进程所拥有。但是更好的方法是由操作系统所有。
同步 / 异步
同步 / 异步,也称 阻塞(blocking) / 非阻塞(nonblocking)。分几种情况:
- 发送方发出消息后:
- Blocking send:阻塞直到消息被接收或者入邮箱
- Nonblocking send:不阻塞,继续执行其他操作
- 接受方接收消息时:
- Blocking receive:阻塞直到有消息可被接收
- Nonblocking receive:不阻塞,取到新消息或者空
不同容量的 buffering
如果通讯链路不支持 buffering,即它没有 buffer(一般是消息队列)来存放信息,这要求 blocking send。否则没有此限制。
具体实现例子
共享内存
见 OS: Process: IPC: Shared Memory。