数据结构:
1.ipc_perm
系统使用ipc_perm 结构来保存每个IPC 对象权限信息。在Linux 的库文件linux/ipc.h
中,它是这样定义的:
struct ipc_perm
{
key_t key;
ushort uid; /* owner euid and egid */
ushort gid;
ushort cuid; /* creator euid and egid */
ushort cgid;
ushort mode; /* access modes see mode flags below */
ushort seq; /* slot usage sequence number */
};
结构里的前几个成员的含义是明显的,分别是IPC 对象的关键字,uid 和gid。然后是
IPC 对象的创建者的 uid 和gid。接下来的是IPC 对象的存取权限。最后一个成员也许有点
难于理解,不过不要担心,这是系统保存的IPC 对象的使用频率信息,我们完全可以不去
理会它。
2.msgbuf
消息队列最大的灵活性在于,我们可以自己定义传递给队列的消息的数据类型的。不
过这个类型并不是随便定义的,msgbuf 结构给了我们一个这类数据类型的基本结构定义。
在Linux 的系统库linux/msg.h 中,它是这样定义的:
/* message buffer for msgsnd and msgrcv calls */
struct msgbuf {
long mtype; /* type of message */
char mtext[1]; /* message text */
};
它有两个成员:
mtype 是一个正的长整型量,通过它来区分不同的消息数据类型。
mtext 是消息数据的内容。
通过设定mtype 值,我们可以进行单个消息队列的多向通讯。如下图,client 可以给它
向server 发送的信息赋于一个特定的mtype 值,而server 向client 的信息则用另一个mtype
值来标志。这样,通过mtype 值就可以区分这两向不同的数据。
利用相同的原理,可以实现更复杂的例子。
需要注意的是,虽然消息的内容mtext 在msgbuf 中只是一个字符数组,但事实上,在
我们定义的结构中,和它对应的部分可以是任意的数据类型,甚至是多个数据类型的集合。
比如我们可以定义这样的一个消息类型:
struct my_msgbuf {
long mtype; /* Message type */
long request_id; /* Request identifier */
struct client info; /* Client information structure */
};
在这里,与mtext 对应的是两个数据类型,其中一个还是struct 类型。由此可见消息队
列在传送消息上的灵活性。
不过,虽然没有类型上的限制,但Linux 系统还是对消息类型的最大长度做出了限制。
在Linux 的库文件linux/msg.h 中定义了每个msgbuf 结构的最大长度:
#define MSGMAX 4056 /* <= 4056 */ /* max size of message (bytes) */
也即是说,包括mtype 所占用的4 个字节,每个msgbuf 结构最多只能只能占用4056
字节的空间
3.msg
消息队列在系统内核中是以消息链表的形式出现的。而完成消息链表每个节点结构定
义的就是msg 结构。它在Linux 的系统库linux/msg.h 中的定义是这样的:
/* one msg structure for each message */
struct msg {
struct msg *msg_next; /* next message on queue */
long msg_type;
char *msg_spot; /* message text address */
time_t msg_stime; /* msgsnd time */
short msg_ts; /* message text size */
};
msg_next 成员是指向消息链表中下一个节点的指针,依靠它对整个消息链表进行访问。
msg_type 和msgbuf 中mtype 成员的意义是一样的。
msg_spot 成员指针指出了消息内容(就是msgbuf 结构中的mtext)在内存中的位置。
msg_ts 成员指出了消息内容的长度。
4.msgqid_ds
msgqid_ds 结构被系统内核用来保存消息队列对象有关数据。内核中存在的每个消息
队列对象系统都保存一个msgqid_ds 结构的数据存放该对象的各种信息。在Linux 的库文
件linux/msg.h 中,它的定义是这样的:
/* one msqid structure for each queue on the system */
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue */
struct msg *msg_last; /* last message in queue */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
struct wait_queue *wwait;
struct wait_queue *rwait;
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 */
};
其中,
msg_perm 成员保存了消息队列的存取权限以及其他一些信息(见上面关于ipc_perm
结构的介绍)。
msg_first 成员指针保存了消息队列(链表)中第一个成员的地址。
msg_last 成员指针保存了消息队列中最后一个成员的地址。
msg_stime 成员保存了最近一次队列接受消息的时间。
msg_rtime 成员保存了最近一次从队列中取出消息的时间。
msg_ctime 成员保存了最近一次队列发生改动的时间。
wwait 和rwait 是指向系统内部等待队列的指针。
msg_cbytes 成员保存着队列总共占用内存的字节数。
msg_qnum 成员保存着队列里保存的消息数目。
msg_qbytes 成员保存着队列所占用内存的最大字节数。
msg_lspid 成员保存着最近一次向队列发送消息的进程的pid。
msg_lrpid 成员保存着最近一次从队列中取出消息的进程的pid。