我是zoro
分类: LINUX
2010-10-03 12:08:37
1.标识符和键
每个内核中的IPC结构(消息对了、信号量或共享存储段)都有一个非负整数(int型)的标识符(identifier)加以引用。标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上会合,需要提供外部名。为此使用了键(key),每个IPC对象都与一个键相关联,于是键就用做为该对象的外部名。
键的数据类型是基本系统数据类型key_t,通常在头文件
产生一个键:
#include
#include
key_t ftok(const char *pathname, int proj_id); //path引用一个现存文件,只使用id参数的低8位。
返回值:成功返回键,出错返回(key_t)-1。
此后可以使用 IPC 对象的 get 函数(在下面说明这些函数)创建或访问指定的 IPC 对象。这些函
数共有的规则是:
•key参数为 IPC_PRIVATE 的话表示创建一个新的 IPC 对象;
•key没有被现有的 IPC 对象使用,并在参数 flag 中指定 IPC_CREAT 时,也创建一个新的 IPC 对象;判定 key 是否已经被使用,可以在 flag 中指定 IPC_EXCL;
• 否则,get 函数则用于通过指定的 key 获得对应 IPC 对象的标识符;
访问模式
消息队列和共享内存包括“读”和“写”两种访问模式,而信号量为“读”和“更改”两种模 式。
IPC 对象的主要优点和缺点:
• 需要自己设计引用计数等释放对象的规则;
• 不属于文件范畴,不能使用文件系统的 open(2)、read(2)、write(2)等 I/O 函数,故也不能 利用已有的高级 I/O 机制并行地访问多个 IPC 对象;
2.消息队列
消息队列是消息的连接表,存放在内核中并由消息队列标识符标志。
①打开一个现存队列或创建一个新队列
调用的第一个函数通常是msgget,其功能是打开一个现存队列或创建一个新队列。
#include
#include
#include
int msgget(key_t key, int msgflg);
返回值:成功返回消息队列ID,出错返回-1。
The
msqid_ds data structure is defined in
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in queue (non-standard) */
msgqnum_t msg_qnum; /* Current number of messages in queue */
msglen_t msg_qbytes; /* Maximum number of bytes allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
②msgctl函数对队列执行多种操作。
#include
#include
#include
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
返回值:若成功返回0,出错返回-1。
参数: cmd参数说明对msqid指定的队列要执行的命令:
IPC_STAT: 取此队列的msqid_ds结构, 并将它存放在buf指向的结构中.
IPC_SET: 按由buf指向结构中的值, 设置与此队列相关结构中的msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes. 该命令只有下列两种进程可以执行:
有效用户ID等于msg_perm.cuid或msg_per.uid.
具有超级用户特权的进程.
IPC_RMID: 从系统中删除该消息队列以及仍在该队列中的所有数据. 执行权限同上.
③msgsnd函数将数据放到消息队列中
#include
#include
#include
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
返回值:若成功返回0,出错返回-1。
ptr参数指向一个长整型数,它包含了正的整型消息类型,其后紧跟着消息数据(若msgsz是0,则无消息数据)。ptr就是一个指向msgbuf结构的指针。接收者可以使用消息类型以非先进先出的次序取消息。
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[msgsz]; /* message data ,of length msgsz*/
};
flag 一般为0,也可以为 IPC_NOWAIT(类似文件I/O的非阻塞I/O标志,不使用的话在队列已经满的时候将被阻塞,直到有信号被递送或 者队列腾出空间)。
④msgrcv从队列中取用消息
#include
#include
#include
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
返回值:成功返回消息数据部分的长度,出错返回-1.
参数 msgtyp使我们可以指定想要哪一种消息:
msgtyp==0 返回队列中的第一个消息。
msgtyp>0 返回队列中消息类型为 msgtyp的第一个消息。
msgtyp<0 返回队列中消息类型值小于或等于 msgtyp绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
当msgrcv成功返回时, 与消息队列相关的msqid_ds结构被更新, 以指示调用者的进程ID(msg_lrpid), 调用时间(msg_rtime)和队列中的消息数(msg_qnum)减1.