825 字
4 分钟
进程间通信如何选择?管道、共享内存、信号和 Socket
IPC 选择先看通信双方是否同机、是否有亲缘关系、传输是字节流还是离散消息、数据量多大,以及是否需要请求响应或广播。没有一种 IPC 在所有维度都最好。
- 匿名管道适合有亲缘关系进程间的简单字节流,常见于 shell 管道;通常需约定方向和数据帧格式,管道有有限缓冲容量,读写关闭会影响对端行为。
- **命名管道(FIFO)**通过文件系统名字让无亲缘进程也能连接,仍是本机字节流,不自动提供消息边界或跨机器能力。
- 消息队列适合内核代为排队的离散消息,接收方可按接口规则取消息;队列容量与单条消息大小有限,数据通常还需在用户态和内核态间复制。
- 共享内存适合本机大块或高频数据交换,多个进程映射同一存储区域,避免每次经内核消息通道搬运整块内容。但它不自带读写顺序或互斥协议,必须配合进程共享互斥锁、信号量、原子状态或其他同步设计,并处理初始化、崩溃清理和共享数据布局。
- Socket可用于本机 Unix domain 通信,也可用于网络跨主机通信;能构建双向流或数据报,但需处理部分读写、连接错误、协议和序列化。
- 信号适合通知“事件发生”,不适合承载大块业务数据。普通信号通常不排队;实时信号可携带有限的附加值,具体能力依系统接口。信号量则是同步原语,通过许可计数协调资源或事件,不负责传递业务消息。
共享内存“不经过内核搬运每条消息”不等于绝对零成本:建映射、锁竞争、缓存一致性和拷贝应用数据仍有成本。数据少且频率低时,管道或 Socket 往往更易维护;跨机器则使用网络协议或在 Socket 之上使用 RPC、消息队列等应用方案。
常见追问
Q:匿名管道与命名管道最主要的区别?
A:匿名管道通常靠继承的文件描述符在相关进程间通信;FIFO 有文件系统路径,可由无亲缘进程按名字打开,但两者本质上都提供本机字节流。
Q:共享内存为什么还需要信号量或锁?
A:共享内存只让双方访问同一数据区域,不保证一个进程写到一半时另一个不会读取,也不负责通知数据何时准备好。
Q:信号能携带任意消息吗?
A:不能。信号主要用于事件通知;实时信号可能携带有限值,但大块或可靠队列消息应使用管道、消息队列或 Socket。
Q:什么时候选 Socket 而非共享内存?
A:需要跨主机、独立服务进程、明确的流/数据报接口或更好隔离时,Socket 通常更合适;本机极高吞吐共享数据可评估共享内存,但同步成本需纳入设计。
进程间通信如何选择?管道、共享内存、信号和 Socket
https://blog.xqcherry.top/posts/interview/operating-system/ipc-selection-guide/ 目录