消息队列(Message Queues)有关的数据结构 ipc_perm msgbuf msg msqid_ds

在介绍消息队列的使用前,让我们先熟悉一下在后面会碰到的几个和消息队列有关的

数据结构:

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。

你可能感兴趣的:(Linux)