1、System V IPC
System V IPC包含消息队列、信号量和共享内存。其主要是利用key_t键创建相应的IPC。可利用ipcs或ipcrm命令对System V消息队列、信号量和共享内存进行查询或删除。
下表是所有System V IPC函数:
消息队列 | 信号量 | 共享内存区 | |
头文件 | <sys/msg.h> | <sys/sem.h> | <sys/shm.h> |
创建或打开IPC的函数 | msgget | semget | shmget |
控制IPC操作的函数 | msgctl | semctl | shmctl |
IPC操作函数 | msgsnd msgrcv | semop | shmat shmdt |
三种类型的System V IPC使用key_t值作为它们的名字、
函数ftok把一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键。
#include<sys/ipc.h>
key_t ftok(const char* pathname, int id);
//返回:若成功则为IPC键,若出错则为-1
key_t键还可以使用IPC_PRIVATE,即保证会创建一个新的唯一的IPC对象。
2、创建与打开IPC通道
对于XXXget函数的第一个参数key是类型为key_t的IPC键。返回值identifier是一个整数标识符。对于key值,可有两种选择。
i、调用ftok,给它传递pathname和id。
ii、指定key为IPC_PRIVATE,这将保证会创建一个新的,唯一的IPC对象。
创建或打开一个IPC对象的逻辑图:
对XXXget函数的其中一个参数oflag进行说明,它指定IPC对象的读写权限位(ipc_perm结构的mode成员),并选择是创建一个新的IPC对象还是访问一个已存在的IPC对象,选择规则如下:
i、指定key为IPC_PRIVATE能保证创建一个唯一的IPC对象。没有一对id和pathname的组合会导致ftok产生IPC_PRIVATE这个键值。
ii、设置oflag参数的IPC_CREAT位但不设置它的IPC_EXCL位时,如果所指定键的IPC对象不存在,那就创建一个新的对象并初始化哈,否则返回该对象。
iii、同时设置oflag的IPC_CREAT和IPC_EXCL位时,如果所指定键的IPC对象不存在,那就创建一个新的对象,否则返回一个EEXIST错误,因为该对象已存在。
3、IPC权限
当使用某个XXXget函数(指定IPC_CREAT标志)创建一个新的IPC对象时,以下信息保存到该对象的ipc_perm结构中。
i、oflag参数中某些位初始化ipc_perm结构的mode成员。如下表所示
数字制 (八进制) | 符号值 | 说明 | ||
消息队列 | 信号量 | 共享内存区 | ||
0400 0200 | MSG_R MSG_W | SEM_R SEM_W | SHM_R SHM_W | 由用户(属主)读 |
由用户(属主)写 | ||||
0040 0020 | MSG_R>>3 MSG_W>>3 | SEM_R>>3 SEM_W>>3 | SHM_R>>3 SHM_W>>3 | 由(属)组成员读 |
由(属)组成员写 | ||||
0004 0002 | MSG_R>>6 MSG_W>>6 | SEM_R>>6 SEM_W>>6 | SHM_R>>6 SHM_W>>6 | 由其他用户读 |
由其他用户写 |
ii、cuid和cgid成员分别设置为调用进程的有效用户ID和有效组ID。这两个成员合称为创建者ID
iii、ipc_perm结构的uid和gid成员分别设置为调用进程的有效用户ID和有效组ID。这两创建者ID却从不改变。这三个XXXctl还允许一个进程修改某个IPC对象的mode成员。
一个小小的技巧:当明确已知对象IPC存在后,使用XXXget,指定oflag为0即可。
每当一个进程访问某个IPC对象时,IPC就执行两级检查,该IPC对象被打开时(XXXget函数)执行一次,以后每次使用对象的执行一次。
(1)每当有一个进程访问某个XXXget函数建立访问某个已存在IPC对象的通道时,IPC就执行一次检查,验证调用者的oflag参数没有指定不在该对象ipc_perm结构mode成员中的任何访问位。
(2)每次IPC操作都对使用该操作的进程执行一次权限测试。
i、如果当前进程的有效用户ID为0(超级用户),那就允许访问。
ii、如果当前进程的有效用户ID等于该IPC对象的的uid值或cuid值,而且相应的访问位在该IPC对象的mode成员中是打开的,那么赋予访问权。
此处相应的访问权限位的意思是:如果当前进程为读访问而打开该IPC对象,那么用户读权限位必须设置;如果当前进程为写访问而打开该IPC对象,那么用忘掉写权限位必须设置。
iii、如果当前进程的有效组ID等于该IPC对象的gid或cgid值 ,而且相应的访问位在该IPC对象的mode成员中是打开的,那么赋予访问权。
iv、如果上面的测试没有一个为真,那么相应的“其他用户”访问位在该IPC对象的mode成员中必须是打开的才能赋予访问权。
以上知识点来均来自steven先生所著UNP卷二(version2),刚开始学习网络编程,如有不正确之处请大家多多指正。