附录1:参考文献[unix网络编程第二卷:进程间的通信]给出了IPC随进程持续、内核持续以及随文件系统持续的定义:
1、岁进程持续:IPC一直存在到打开IPC对象的最后一个进程关闭此对象为止。如管道和命名管道
2、随内核持续:IPC一直持续到内核重新自举或者显示删除该对象为止。如消息队列、信号灯以及共享内存等;
3、随文件系统持续:IPC一直持续到显示删除该对象为止
消息队列(报文队列)能够克服早起unix通信机制的一些缺点
信号通信方式更想“即时”的通信方式,他要求信号的进程在某个时间范围内对信号做出反应,信号只是在进程生命周期内有意思,信号所传递的信息是接近于随进程持续的概念,见附录1;缺点:只能传输无格式的字节流,缓冲区大小受限
消息队列即一个消息链表。消息则看做一个记录,具有特定格式以及优先级。
对消息队列有写权限的进程可以向队列中按照一定的规则添加新的消息,对于消息队列有读权限的进程可以从消息队列中读走消息,消息队列时内核持续的。
(?消息队列中消息被读取之后是否被从消息队列中删除?)
系统V消息队列
1、随内核持续,只有内核重启或显式删除一个消息队列时,才被真正删除。
系统中记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中,
系统中所有消息队列都可以在msg_ids中找到访问入口
2、消息队列时一个消息链表,每个都有一个队列头,结构(struct msg_queue参见附录2)
包括大量信息,可以设置其中信息,此结构位于内核中
3、内核与消息队列建立联系:
通过struct ipc_ids msg_ids访问到每个消息队列头的第一个成员:struct kern_ipc_perm;
通过 struct kern_ipc_perm 唯一的确定一个消息队列(根据key)
对消息队列的操作
1、打开和创建消息队列
文件名到键值
#include <sys/types.h> #include <sys/ipc.h> key_t ftok (char*pathname, char proj);
消息缓冲区结构
struct msgbuf{ long mtype; char mtext[1]; };
3.系统V消息队列API
系统V消息队列API共有四个,使用时需要包括几个头文件:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
1)int msgget(key_t key, int msgflg)
参数key是一个键值,由ftok获得;msgflg参数是一些标志位。该调用返回与健值key相对应的消息队列描述字。
在以下两种情况下,该调用将创建一个新的消息队列:
参数msgflg可以为以下:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或结果。
调用返回:成功返回消息队列描述字,否则返回-1
注:参数key设置成常数IPC_PRIVATE并不意味着其他进程不能访问该消息队列,只意味着即将创建新的消息队列。
2)int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。
msqid为消息队列描述字;消息返回后存储在msgp指向的地址,msgsz指定msgbuf的mtext成员的长度(即消息内容的长度),msgtyp为请求读取的消息类型;读消息标志msgflg可以为以下几个常值的或:
msgrcv手册中详细给出了消息类型取不同值时(>0; <0; =0),调用将返回消息队列中的哪个消息。
msgrcv()解除阻塞的条件有三个:
调用返回:成功返回读出消息的实际字节数,否则返回-1。
3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
向msgid代表的消息队列发送一个消息,即将发送的消息存储在msgp指向的msgbuf结构中,消息的大小由msgze指定。
对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。造成msgsnd()等待的条件有两种:
msgsnd()解除阻塞的条件有三个:
调用返回:成功返回0,否则返回-1。
4)int msgctl(int msqid, int cmd, struct msqid_ds *buf);
该系统调用对由msqid标识的消息队列执行cmd操作,共有三种cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。
调用返回:成功返回0,否则返回-1。
附录2:
结构msg_queue用来描述消息队列头,存在于系统空间
struct msg_queue { struct kern_ipc_perm q_perm; time_t q_stime; /* last msgsnd time */ time_t q_rtime; /* last msgrcv time */ time_t q_ctime; /* last change time */ unsigned long q_cbytes; /* current number of bytes on queue */ unsigned long q_qnum; /* number of messages in queue */ unsigned long q_qbytes; /* max number of bytes on queue */ pid_t q_lspid; /* pid of last msgsnd */ pid_t q_lrpid; /* last receive pid */ struct list_head q_messages; struct list_head q_receivers; struct list_head q_senders; };
结构msqid_ds用来设置或返回消息队列的信息,存在于用户空间;
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue,unused */
struct msg *msg_last; /* last message in queue,unused */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
unsigned short msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
参考文献: