UNIX/Linux进程间通信IPC系列(一)总论

XSI IPC总论

 

有三种IPC我们称作XSI IPC,即消息队列、信号量、共享存储器。它们之间有很多相似之处。

XSI IPC源自systemVIPC功能,由于XSI IPC不使用文件系统的名字空间,而是构造了它们自己的名字空间,为此常常受到批评。(POSIX IPC 使用的是文件系统的名字空间,但我发现很多Linux发行版都不支持POSIX IPC,而systemV IPC却有广泛的支持,故我们只讨论systemV IPC

 

 

消息队列

信号量

共享内存区

头文件

<sys/msg.h>

<sys/sem.h>

<sys/shm.h>

创建/打开IPC的函数

msgget

semget

shmget

控制IPC操作的函数

msgctl

semctl

shmctl

IPC操作函数

msgsnd

msgrcv

semop

shmat

shmdt

 

标识符和键

每个内核中的IPC结构(消息队列、信号量、共享存储段)都用一个非负整数的标识符加以引用。与文件描述符不同,IPC标识符不是小整数

标识符是IPC对象的内部名。(它是在同种IPC内部循环增长的整型数,即不同种类的IPC对象可能重名,但同种IPC对象不会重名)为使多个合作进程能在同一IPC对象上会合,需要提供一个外部名方案。为此使用(key),每个IPC对象都与一个键相关联,于是键就用作该对象的外部名

键的数据类型是key_t,通常在头文件<sys/types.h>中被定义为长整型。

 

有以下几种方法使客户进程和服务器进程在同一IPC结构上会合:

1、服务器进程可以指定键IPC_PRIVATE创建一个新IPC结构,将返回的标识符存放在文件中,以便客户进程取用。(要读写文件,不好)

2、在一个公用头文件中定义一个客户进程和服务器进程都认可的键。(但此键可能已被占用)

3、客户进程和服务器进程认同一个路径名和项目ID(0—255),接着调用函数ftok将这两个值变换为一个键。然后再方法2中使用此键。(这样可避免键名重复问题)

 

#include <sys/ipc.h>

key_t  ftok (const char*path,  int id) ;

ftok就是由一个路径名和项目ID产生一个键。

参数path必须引用一个现存文档。

 

权限结构

内核给每个IPC对象维护一个信息结构,该结构规定了权限和所有者。其内容跟内核给文件维护的信息类似。

#include <sys/ipc.h>

struct  ipc_perm {

      uid_t  uid ;

      gid_t  gid ;

      uid_t  cuid ;

      gid_t  cgid ;

      mode_t mode ;

      key_t  key ;

      ……….

} ;

在创建IPC结构时,对所有字段都赋初值。以后,可以调用msgctlsemctlshmctl修改uidgidmode字段。

 

创建/打开IPC通道

创建/打开一个IPC对象的三个XXXget函数,第一个参数key是类型为key_t的键。返回一个整数标识符。

对于key值,应用程序有两种选择:

1、调用ftok,给它传递pathnameid

2、指定keyIPC_PRIVATE,这将保证会创建一个新的、唯一的IPC对象。

(注意:为访问一个现存IPC对象,绝不能指定IPC_PRIVATE作为键。因为这是一个特殊的键值,它总是用于创建一个新IPC对象)

 

三个XXXget函数的oflag参数,它指定IPC对象的读写权限位(ipc_perm结构的mode成员),并选择是创建一个新的IPC对象还是访问一个已存在的IPC对象。

IPC对象来说,IPC_CREATIPC_EXCL的组合跟open函数的O_CREATO_EXCL的组合类似。

 

若是创建IPC对象,则必须要指定IPC_CREAT标志。

若是打开IPC对象,则把此标志位置为NULL

 

 

 

UNIX/Linux进程间通信IPC系列(一)总论

上一篇:设计原则—依赖倒置原则


下一篇:python--基本数据类型