进程间通信
2025/9/4...大约 3 分钟OS
1 概览
进程间通信是操作系统提供的一种机制,用于不同的,相互资源隔离的进程之间交换信息。
进程间通信方式汇总如下:
IPC方式 | 优点 | 缺点 | 典型用途 |
---|---|---|---|
匿名管道 | - 实现简单 - 父子进程间快速通信 | - 仅限亲缘进程 - 半双工通信 - 不支持随机访问 | 父子进程之间的数据传输 |
命名管道 (FIFO) | - 可用于无亲缘关系进程 - 文件系统中可见 | - 半双工通信 - 性能一般 - 编程略复杂 | 多进程之间的简单通信 |
消息队列 | - 支持结构化消息 - 异步通信 - 可设置优先级 | - 消息大小有限 - 内核态拷贝影响性能 - 编程复杂度中等 | 多进程异步消息传递 |
共享内存 | - 最快速的通信方式 - 支持大数据量传输 | - 需额外同步机制(如信号量) - 编程复杂 - 易出错 | 高性能数据交换 图像/视频处理 |
信号量 | - 控制资源访问 - 支持进程同步与互斥 | - 不传输数据 - 易死锁 - 编程复杂 | 临界区保护 生产者-消费者模型 |
信号 | - 异步事件通知 - 系统支持广泛 | - 信息量少(仅编号) - 信号处理函数复杂 | 中断处理 定时器通知 |
套接字(Socket) | - 支持本地与网络通信 - 双向通信 - 灵活强大 | - 编程复杂 - 性能略低于共享内存(协议栈开销) | 客户端-服务器模型 跨主机通信 |
UNIX域套接字 | - 本地进程通信 - 支持双向传输 - 性能优于网络套接字 | - 仅限本机使用 - 编程仍需处理协议细节 | 本地服务组件之间的通信 |
2 进程间数据的同步机制
从文章开头我们了解到了进程间的通信方式有哪些,但是更加重要的是如何实现进程间数据的同步原语。换句话说,读者进程需要知道什么时候数据可读,写者进程需要知道什么时候数据可写。
当然,不是所有的进程间的通信方式都需要同步语义,如果对进程加数据的读写都是阻塞式的同步行为,那么也不会存在竞态条件了,比如说像管道, socket,消息队列这些通信方式本来就提供了阻塞式和非阻塞式的读写接口,那如果不考虑性能和并发,你大可以使用阻塞式的读写方式来读写数据,当然,大部分情况你往往都不能这么写。
所以我们讨论的是进程间数据的异步通信下的同步机制,我们以共享内存为例,看下有哪些实现方式。
2.1 POSIX + 信号量
基础控制原理是通过进程级别的信号量,写者B写完数据后通知读者A可读,读者A读完数据后通知写着B可写:
- 使用两个信号量:
sem_w
控制进程B的写权限,sem_r
控制进程A的读权限。 - 初始状态:
sem_w = 1
(允许写),sem_r = 0
(禁止读)
大致的一个同步流程设计如下:
步骤 | 写者进程 B | 读者进程 A |
---|---|---|
1 | sem_wait(sem_w) 等待写权限 | — |
2 | 写入共享内存 | — |
3 | sem_post(sem_r) 通知读者 | — |
4 | — | sem_wait(sem_r) 等待读权限 |
5 | — | 读取共享内存 |
6 | — | sem_post(sem_w) 通知写者可以继续写 |