# 7.1 POSIX IPC 介绍

Linux/Unix 上的 IPC（进程间通信）方法一般分为 System V IPC 与 POSIX IPC 两种。POSIX IPC 是对 System V IPC 的改进，但 System V IPC 移植性较好，因为比较久远。 System V IPC 工具具有以下缺点：

* System V IPC 是无连接的，意味着内核无法维护当前使用该对象的引用计数，所以应用程序需要使用额外的代码来知道合适可以删除一个对象。
* System V IPC 编程接口与传统 UNIX I/O 模型不一致，使用了整数键值和 IPC 标识符来引用一个 IPC 对象，而不是路径名和文件描述符。使得编程接口十分复杂。

POSIX IPC 工具则消除了上面两个缺点，提供更简单的接口也更加符合传统的 UNIX 模型。所以这里主要对 POSIX IPC 作介绍。&#x20;

在 Linux 上使用 POSIX IPC 机制需要与实时库 librt 链接起来，即指定 -lrt 选项。 POSIX IPC 对象编程接口总结：&#x20;

<figure><img src="https://2210531937-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBlhv2ECKp6X7qkBSugdB%2Fuploads%2F2RdpOLnv777JvfALTalK%2Fimage.png?alt=media&#x26;token=37376f86-a663-41b7-b984-ceec74061632" alt=""><figcaption></figcaption></figure>

### IPC 对象名字

要访问一个 POSIX IPC 对象就必须要通过某种方式来识别出它。在 SUSv3 中规定的唯一一种用来标识 POSIX IPC 对象的可移植的方式是使用以斜线打头后面跟着一个或多个非斜线字符的名字，如/myobject。但也没有禁止形式与此不同的名字。

### 创建或打开对象

每种 IPC 机制都有一个关联的 open 调用（mq\_open()、sem\_open()以及 shm\_open()），它与用于打开文件的传统的 UNIX open()系统调用类似。给定一个 IPC 对象名，IPC open 调用会完成下列两个任务中的一个：

* 使用给定名字创建一个对象，并打开此对象，返回其句柄
* 打开一个已有对象并返回其句柄

IPC open 调用返回句柄与传统 open 调用返回文件描述符类似。所有的 IPC open 调用至少需要三个参数：

* name：标识待创建或待打开的对象
* oflag：位掩码，一般包含
  * O\_CREAT：对象不存在则创建，如果没有指定这个标记，且对象不存在则返回 ENOENT 错误
  * O\_EXCL：如果同时也指定了 O\_CREAT 并且对象已经存在，那么就返回一个错误（EEXIST）。这两步是原子操作（5.1 节）。这个标记在不指定 O\_CREAT 时是不起作用的
  * O\_RDONLY、O\_WRONLY、O\_RDWR 与 open 中的含义一致
* mode：权限掩码，与文件上的 open 一致

### 关闭 IPC 对象

消息队列和信号量调用对应的 close 函数即可关闭，POSIX 共享内存对象则通过 munmap 解除映射。

&#x20;IPC 对象在进程终止或执行 exec 时会自动被关闭。

### IPC 对象删除和对象持久性

与打开文件一样，POSIX IPC 对象也有引用计数，内核会维护对象上的打开引用计数。与 System V IPC 对象相比，这种方式使得应用程序能够更加容易地确定何时可以安全地删除一个对象。

每个 IPC 对象都有一个对应的 unlink 调用，其操作类似于应用于文件的传统的 unlink 系统调用。unlink 调用会立即删除对象的名字，然后在所有进程使用完对象（即当引用计数等于 0 时）之后销毁该对象。 当一个对象被断开链接之后，指定同一个对象名的 IPC open 调用将会引用一个新对象（在不指定 O\_CREAT 时会失败）。&#x20;

与 System V IPC 一样，POSIX IPC 对象也拥有内核持久性。对象一旦被创建，就会一直存在直到被断开链接或系统被关闭。这样一个进程就能够创建一个对象、修改其状态，然后退出并将对象留给在后面某个时刻启动的一些进程访问。
