IPC对象是活动在核心级别的一种进程间通信的工具。存在的IPC对象通过它的标识符来引用和访问,这个标识符是一个非负整数,它唯一的标识了一个IPC对象,这个IPC对象可以是讯息伫列或信号量或共享存储器中的任意一种类型。在Linux系统中标识符被声明成整数,所以可能存在的最大标识符为65535。这里标识符与档案描述符有所不同,使用open函式打开一个档案时,返回的档案描述符的值为当前进程最小可用的档案描述符数组的下标。IPC对象删除或创建时相应的标识符的值会不断增加到最大的值,归零循环分配使用。
基本介绍
- 中文名:IPC对象
- 定义:核心级别的一种进程间通信的工具
- 最大标识符:为65535
- 类型:讯息伫列或信号量
- 目的:使通信质量更加完美
- 注意:系统为IPC对象保存ipc_perm
IPC对象的概念
IPC的标识符只解决了内部访问一个IPC对象的问题,如何让多个进程都访问某一个特定的IPC对象还需要一个外部键(key),每一个IPC对象都与一个键相关联。这样就解决了多进程在一个IPC对象上汇合的问题。创建一个IPC对象时需要指定一个键值,类型为key_t,在<sys/types.h>中定义为一个长整型。键值到标识符的转换是由系统核心来维护的。当有了一个IPC对象的键值,如何让多个进程知道这个键,可以有多种实现的办法。
ipc的概念

● 可以使用档案来做中间的通道,创建IPC对象进程,使用键IPC_PRIVATE成功建立IPC对象之后,将返回的标识符存储在一个档案中。其他进程通过读取这个标识符来引用IPC对象通信。
● 定义一个多个进程都认可的键,每个进程使用这个键来引用IPC对象,值得注意的是,创建IPC对象的进程中,创建IPC对象时如果该键值已经与一个IPC对象结合,则应该删除该IPC对象,再创建一个新的IPC对象。
● 多进程通信中,对于指定键引用一个IPC对象而言,可能不具有拓展性,并且在该键值已经被一个IPC对象结合的情况下。所以必须删除这个存在对象之后再建立一个新的。这有可能影响到其他正在使用这个对象的进程。函式ftok可以在一定程度上解决这个问题,
函式ftok可以使用两个参数生成一个键值,函式原型如下:
#include <sys/ipc.h>
key_t ftok( const char *path, int id );
函式中参数path是一个档案名称。函式中进行的操作是,取该档案的stat结构的st_dev成员和st_ino成员的部分值,然后与参数ID的低八位结合起来生成一个键值。由于只是使用st_dev和st_ino的部分值,所以会丢失信息,不排除两个不同档案使用同一个ID,得到同样键值的情况。
系统为每一个IPC对象保存一个ipc_perm结构体,该结构说明了IPC对象的许可权和所有者,每一个版本的核心各有不用的ipc_perm结构成员。若要查看详细的定义请参阅档案<sys/ipc.h>。
struct ipc_perm {
key_t key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
unsigned short mode;
unsigned short seq;
};
每一种版本的ipc_perm结构体定义至少要包含上述几个域。当调用IPC对象的创建函式(semget msgget shmget )时,会对ipc_perm结构的每一个域赋值。在后续的操作中如需修改这几个域则调用相应的控制函式(msgctl semctl shmctl)。
%注意:只有超级用户或者创建IPC对象的进程有权改变ipc_perm结构的值。结构中的mode域类似于档案的stat结构的mode域,但是不可以有执行许可权。mode值描述如表14-3所示。
ipc_perm的mode详解表
操作者 | 读 | 写(更改 更新) | 操作者 | 读 | 写(更改 更新) |
用户 | 0400 | 0200 | 其他 | 0004 | 0002 |
组 | 0040 | 0020 |
IPC对象的问题
IPC对象所存在的问题主要集中在以下几点:
过于繁杂的编程接口,比起使用其他通信方式,IPC所要求的代码量要明显增多。
● IPC不使用通用的档案系统,这也是饱受指责的原因。所以不能使用标準I/O操作函式来读写IPC对象。为此不得不新增加一些函式来支持必要的一些操作(例如msgget msgrev msgctl等)并且对于不同类型的IPC对象都有一系列特定的操作函式。由于IPC不使用档案描述符,所以不能使用多路I/O监控函式select及poll函式来操作IPC对象。
● 缺少的资源回收机制。由于IPC对象在使用过程中并不保存引用计数,所以当出现一个进程创建了IPC对象然后退出时,则这个对象只有在出现后面几种情况才会被释放或者删除,即由某一个进程读出讯息,或者IPC的所有者或超级用户删除了这个对象。这也是IPC相对于管道或FIFO所欠缺的资源回收机制。
IPC对象系统命令
在shell下可以使用一些命令来操作IPC对象,下面通过几个实际的例子来帮助理解IPC对象,使用ipcs可以显示IPC的状态。在shell中输入:
$ipcs –a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 65536 root 600 393216 2dest
0x00000000 2654209 root 666 4096 0
0x00000000 2752516 root 666 4096 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 294911 root 666 1
------ Message Queues --------
key msqid owner perms used-bytes messages
注意ipcs输出的信息中的key 以及shmid,key标识的是IPC对象的外键,shmid标识的IPC对象的标识符。owner标识的是IPC所属的用户,perms标识许可权。可以使用ipcrm命令来删除一个IPC对象,使用实例如下。在shell中输入:
$ipcrm –m 2752516
$ipcs –a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 65536 root 600 393216 2dest
0x00000000 2654209 root 666 4096 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 294911 root 666 1
------ Message Queues --------
key msqid owner perms used-bytes messages
在套用中,如果使用kill命令删除程式后,发现系统资源例如记忆体的使用量仍然很高,则应检查系统IPC状态,并使用ipcrm命令删除不使用的IPC。