Linux继承了system V提供的3种通信方式,分别是消息队列、信号量和共享内存。
11.1system V IPC基础
Linux继承了system V提供的3种通信方式,分别是消息队列、信号量和共享内存。和文件一样,IPC在使用前必须创建,每种IPC都有特定的生产者、所有者和访问权限。使用ipcs可以查看当前系统正在使用的IPC工具。
------ Message Queues --------
key msqid owner perms used-bytes messages
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 294912 vicli 600 524288 2 dest
0x00000000 1474561 vicli 600 524288 2 dest
0x00000000 655362 vicli 600 524288 2 dest
0x00000000 524291 vicli 600 524288 2 dest
0x00000000 753668 vicli 600 524288 2 dest
0x00000000 1048581 vicli 600 524288 2 dest
0x00000000 1146886 vicli 600 524288 2 dest
0x00000000 1310727 vicli 600 524288 2 dest
0x00000000 1212424 vicli 600 67108864 2 dest
0x00000000 1507337 vicli 600 4194304 2 dest
0x00000000 1605642 vicli 600 524288 2 dest
0x00000000 1703947 vicli 600 524288 2 dest
0x00000000 2162700 vicli 600 2097152 2 dest
------ Semaphore Arrays --------
key semid owner perms nsems
由以上可以看出,一个IPC工具至少包含key值,ID值,拥有者,权限和使用大小等。如果需要手工删除某个IPC机制,可以使用ipcm命令。
11.1.1key值和ID值。
linux系统为每个IPC机制都分配了唯一的ID,所有针对该IPC机制的操作都是用该ID值。因此,通信的双方都需要通过某个办法来获取ID值。创建者根据创建函数的返回值可获取该值,由于Linux两个进程不能随便访问对方的空间(除非父子进程,子继承父,实现父亲向子的单向传递),另一进程也就不能直接获取这一ID值。
为了解决这个问题,IPC在实现时约定使用key值作为参数创建,如果在创建时使用相同的key值将得到同一个IPC对象的ID,这样就保证了双方可以获取用于传递数据的IPC机制的ID值。key值是一个32位整形数据。
但如果所有程序使用固定的key创建这些IPC机制有违软件设计思想,为了尽可能与系统信息的文件关联,Linux提供ftok来创建key值,在函数的参数中,需要特定的文件作为参数。
extern key_t ftok(__const char *__pathname, int __proj_id);
此函数有两个参数,pathname为路径名,可以是特殊文件,例如目录文件,也可以是当前目录,因为当前目录一般都存在,且不会被立即删除,第2个参数为一个int型变量。
每个文件都有其自身的属性,可以通过stat函数读取,在ftok函数创建key值过程中使用了该文件属性的st_dev和st_ino,集体构成:
key值的第31-24,为ftok第二个参数的低八位。
key值的第23-16为该文件的st_dev属性的低8位。
key值的第15-0为该文件的st_ino属性的低16位。
因此,使用相同的文件路径及整数,得到的key值是唯一的,唯一的key值创建的某类IPC机制时将得到同一个IPC机制(但如果使用相同的key值分别创建一个消息队列和一个信号量,两者没有关系)。
11.1.2拥有者及权限
要访问任何一个IPC工具需要对该IPC工具用有相应的权限,一个IPC工具所具有的IPC访问权限在cat /usr/include/bits/ipc.h 文件中被定义为struct ipc_perm。
struct ipc_perm
{
__key_t __key; /* Key. */
__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. */
unsigned short int mode; /* Read/write permission. */
unsigned short int __pad1;
unsigned short int __seq