进程间通信(IPC)
进程间通信(Inter-Process Communication, IPC)是操作系统为不同进程提供数据交换与同步能力的机制集合。不同 IPC 方式在内核介入程度、传输方向、是否持久化等方面差异显著,工程上需要按场景做选型。
管道(Pipe)
管道是最古老的 UNIX IPC,本质是一块内核缓冲区加两个文件描述符。匿名管道通过 pipe(int fd[2]) 创建,只能在有亲缘关系的进程间使用(典型场景是 shell 命令通过 | 串联);命名管道(FIFO)借助文件系统路径名,允许无亲缘进程访问。
producer consumer
| ^
v |
write(fd[1]) -> [ kernel buffer ] -> read(fd[0])
管道是字节流、无消息边界,容量有限(典型 64KB),读写阻塞语义是同步原语的一部分。
消息队列
消息队列以"消息"为最小单位,每条记录有类型字段,接收方可按类型筛选。System V 消息队列与 POSIX mq_* 系列是两种主要实现。优势是异步、解耦、支持优先级;缺点是有上限、内核维护成本较高,高吞吐场景下不如共享内存。
共享内存
共享内存把同一块物理页映射到多个进程的虚拟地址空间,是速度最快的 IPC,因为通信过程不再经过内核拷贝。shmget/mmap 是常见入口。为避免并发写冲突,必须配合信号量或 pthread_mutex (在进程间共享时需放在共享内存中) 等同步机制。常用模式:共享内存 + 信号量/文件锁。
信号(Signal)
信号是异步事件通知机制,适合短事件(SIGTERM、SIGCHLD、SIGUSR1 等),不携带复杂数据。kill、raise、sigaction 是基本 API。现代程序更倾向用信号做"中断/异常"的轻量通知,把数据传递交给其他 IPC。
Socket
Socket 是唯一天然支持跨主机通信的 IPC 形式。本机通信使用 UNIX domain socket(AF_UNIX),效率接近共享内存,且支持字节流(SOCK_STREAM)和数据报(SOCK_DGRAM)两种语义;跨网络则使用 AF_INET/AF_INET6 加 TCP/UDP。
IPC 选型
| 场景 | 推荐机制 |
|---|---|
| 父子进程简单数据流 | 匿名管道 |
| 无亲缘进程、单机、本地字节流 | UNIX domain socket 或 FIFO |
| 大数据量、低延迟 | 共享内存 + 信号量 |
| 跨主机 | TCP/UDP socket |
| 异步事件通知 | 信号、eventfd |
选型核心是三个问题:通信双方关系、性能要求、是否跨主机。