以下内容引述至《Linux/Unix系统编程手册》
IPC工具分类
Unix系统上各种通信和同步工具,根据功能可以分为三类:
- 通信: 这些工具关注进程之间的数据交换
- 同步:这些进程关注进程和线程操作之间的同步
- 信号:在特定场景下仍然可以作为一种同步技术
数据传输
- 字节流:通过管道、FIFO以及数据报socket交换的数据是一个无分隔符的字节流;每个读取操作可能会从IPC工具中读取任意数量的字节,不管写者写入的块的大小是什么
- 消息:通过System V消息队列、POSIX消息队列以及数据报socket交换的数据是以分隔符分隔的消息。每个读取操作读取由写者写入的一整条消息,无法只读取部分消息,而把剩余部分留在IPC工具中,也无法在一个读取操作中读取多余的消息
- 伪终端:伪终端是一种在特殊情况下使用的通信工具
不同于共享内存,差别在于
- 尽管一个数据传输工具可能会有多个读取者,但读取操作是具有破坏性的。读取操作会消耗数据,其他进程将无法获取所消耗的数据
- 读取者和写者进程之间的同步是原子的。如果一个读者试图从一个当前不包含数据的数据传输工具中读取数据,默认情况下读取操作会被阻塞直至一些进程写入数据
共享内存
分为三种共享内存: System V共享内存、POSIX共享内存以及内存映射
- 尽管共享内存的通信速度更快,但速度上的优势是用来弥补需要对在共享内存上发生的操作进行同步的不足的。信号量通常作为同步方法;
- 放入共享内存中的数据对所有共享这块内存的进程可见
同步工具
- 信号量:一个信号量是一个由内核维护的整数,其值永远不会小于0,一个进程可以增加或减小一个信号量的值。如果一个进程试图将信号量的值减小到小于0,那么内核会阻塞该操作直至信号量的值增长到允许执行该操作的程度。
- 文件锁:设计用来协调操作同一文件的多个进程的动作的一种同步方式。也可以用来协调对其他共享资源的访问。分为读(共享)锁和写(互斥)锁
- 互斥量和条件变量:通常用于POSIX线程
IPC工具比较
工具类型 | 用于识别对象的名称 | 用于在程序中引用对象的句柄 |
---|---|---|
管道 | 没有名称 | 文件描述符 |
FIFO | 路径名 | 文件描述符 |
Unix domain socket | 路径名 | 文件描述符 |
Internet domain socket | IP地址+端口号 | 文件描述符 |
System V 消息队列 | System V IPC键 | System V IPC标识符 |
System V 信号量 | System V IPC键 | System V IPC标识符 |
System V 共享内存 | System V IPC键 | System V IPC标识符 |
POSIX 消息队列 | POSIX IPC路径名 | mqd_t(消息队列描述符) |
POSIX 命名信号量 | POSIX IPC路径名 | sem_t *(信号量指针) |
POSIX 无名信号量 | 没有名称 | sem_t*(信号量指针) |
匿名映射 | 没有名称 | 无 |
内存映射文件 | 路径名 | 文件描述符 |
flock()文件锁 | 路径名 | 文件描述符 |
fcntl()文件锁 | 路径名 | 文件描述符 |
功能
各种IPC工具在功能上是存在差异的
- 数据传输工具提供了读取和写入操作,传输的数据只供一个读者进程消耗,内核会自动处理读者和写者之间的流控以及同步
- 其他应用程序的设计则更适合采用共享内存的方式,一个进程通过共享内存能够使数据对共享同一内存区域的所有进程可见,但需要考虑维护共享状态
数据传输工具
- 一些数据传输工具以字节流的形式传输数据,另一些则是面向消息的
- 与其他数据传输工具相比,System V和POSIX消息队列特有的一个特性是他们能够给消息赋一个数值类型或优先级
- 管道、FIFO以及socket是使用文件描述符来实现的,这些IPC都支持一组I/O模型:I/O多路复用、信号驱动的I/O、以及Linux特有的epoll API
- POSIX消息队列提供了一个通知工具
- Unix domain socket 提供了一个特性允许在进程间传递文件描述符
- UDP socket允许一个发送者向多个接收者广播或组播消息
网络通信
只有socket允许进程通过网络来通信,socket一般用在两个域中:一个是Unix domain,允许位于同一系统上的进程进行通信;另一个是Internet domain,允许位于通过TCP/IP网络进行连接的不同主机上的进程进行通信。