3. System V IPC

System V IPC包含三种类型的IPCSystem V消息队列、System V信号量、System V共享内存区

3. System V IPC_第1张图片


1. key_t键和ftok函数

三种类型的System V IPC使用key_t值作为名字。头文件<sys/types.h>定义key_t为一个至少32位的整数。函数ftok把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC

#include <sys/ipc.h> key_t ftok(const char *pathname, int id);

ftok的典型实现调用stat函数,然后组合三个值:stat结构的st_dev信息、stat结构的st_info信息、id的低序8位(不能为0)。不能保证不同的路径名与同一个id的组合产生不同的键。

 

2. ipc_perm结构

内核给每个IPC对象维护一个信息结构,内容跟内核给文件维护的信息类似

struct ipc_perm {
    uid_t        uid;           /* owner’s user id */
    gid_t        gid;           /* owner’s group id */
    uid_t        cuid;          /* creator’s user id */
    gid_t        cgid;          /* creator’s group id */
    mode_t       mode;          /* read-write permissions */
    ulong_t      seq;           /* slot usage sequence number */
    key_t        key;           /* IPC key */
};


3. 创建于打开IPC通道

创建或打开一个IPC对象的三个getXXX函数的第一个参数key有两种选择:调用ftok,传递pathnameid指定keyIPC_PRIVATE,保证创建一个新的、唯一的IPC对象。System V IPC定义了自己的IPC_xxx常值

3. System V IPC_第2张图片

#include <sys/ipc.h> <sys/shm.h> int shmget(key_t key, size_t size, int oflag);
#include <sys/types.h> <sys/ipc.h> <sys/sem.h> int semget(key_t key, int nsems, int oflag);
#include <sys/types.h> <sys/ipc.h> <sys/msg.h> int msgget(key_t key, int oflag);

3. System V IPC_第3张图片

3. System V IPC_第4张图片

 

4. IPC权限

oflag参数某些位初始化ipc_perm结构的mode成员

3. System V IPC_第5张图片

一个进程可通过调用相应IPC机制ctlXXX函数(IPC_SET)修改属主ID,创建者ID却从不改变。三个ctlXXX函数允许一个进程修改某个IPC对象的mode成员。

每当有一个进程访问某个IPC对象,IPC执行两级检查IPC对象被打开时执行一次,每次使用对象时执行一次

  • 每当有一个进程以getXXX函数建立访问某个存在IPC对象的通道时,IPC执行一次初始检查,验证调用者的oflag参数没有指定不在该对象ipc_perm结构mode成员中的任何访问位。创建者和调用者的权限位一致。绕过这种检查的方法:如果已知IPC对象存在,指定一个值为0oflag参数。

  • 每次IPC操作都对使用该操作的进程执行一次权限测试:超级用户总是赋予访问权;如果当前进程的有效用户ID等于IPC对象的uidcuid,而且相应的访问位(如果调用者要在IPC对象执行读操作,那么读位必须设置,如果要执行写操作,那么写位必须设置)在IPC对象的mode成员是打开的。

  • 如果当前进程的有效组ID等于IPC对象的gidcgid,而且相应访问位在IPC对象mode成员中是打开的

  • 如果上面的测试没有一个为真,那么相应的“其他用户”访问位在IPC对象的mode成员中必须是打开的

 

5. 标识符重用

ipc_perm结构的seq变量是一个槽位使用情况序列号,一个由内核为系统每个潜在的IPC对象维护的计数器。每当删除一个IPC对象,内核就递增相应的槽位号,若溢出则循环回0System V IPC标识符是系统范围的,不是特定于进程的。从某个getXXX函数获得一个IPC标识符适用于所有进程。可能导致某些进程尝试不同的小整数标识符,期待找出一个当前允许大家读访问的消息队列。解决办法是把标识符值可能范围扩大到所有整数:每次重用一个IPC表项,把返回给调用者的标识符值增加一个IPC表项数。递增槽位使用情况序列号的另一个原因是避免短时间内重用System V IPC标识符,有助于确保过早终止的服务器重新启动后不会重用标识符。

 

6. ipcs和ipcrm程序

由于System V IPC的三种类型不是以文件系统中的路径名标识的,提供两个特殊程序ipcsipcrmipcs输出有关System V IPC特性的各种信息,ipcrm删除一个System V消息队列、信号量或共享内存区


你可能感兴趣的:(Unix编程)