消息队列介绍

消息队列
消息队列是内核地址空间中的内部链表,通过Linux内核在各个进程之间传递内容。消息顺序地发送到消息队列中,并以几种不同的方式从队列中获取,每个消息队列可以用IPC标识符唯一的进程标识。内核中的消息队列是通过IPC的标识符来区别的,不同的消息队列之间是相互独立的。每个消息队列中的消息,又构成一个独立的链表。
消息队列的本质其实是一个内核提供的链表,内核基于这个链表,实现了一个数据结构,并且通过维护这个数据结构来维护这个消息队列。向消息队列中写数据,实际上是向这个数据结构中插入一个新结点;从消息队列汇总读数据,实际上是从这个数据结构中删除一个结点。

消息缓冲区结构
常用的结构是msgbuf结构,程序员可以以这个结构为模板定义自己的消息结构,在头文件<linux/msg.h>中,它的定义如下:

struct msgbuf{
long mtype;
char mtext[1];
};

在结构msgbuf中有两个成员:
(1)mtype:消息类型,以正数来表示。用户可以给某个消息设定一个类型,可以在消息队列中正确地发送和接受自己的信息。例如,在socket编程过程中,一个服务器可以接受多个客户端的连接,可以为每个客户端设定一个消息类型,服务器和客户端之间的通信可以通过此类消息类型来发送和接受消息,并且多个客户端之间通过消息类型来区分。
(2)mtex:消息数据
消息数据的类型为char,长度为1.在构建自己的消息结构时,这个域并不一定要设为char或者长度为1.可以根据实际的情况进行设定,这个域能存放任意形式的任意数据,应用程序编程人员可以重新定义msgbuf结构。

struct msgbuf{
long mtype;
char mtext[10];
long length;
};

上面定义的消息结构与系统定义的不一致,但是mtype是一致的。消息在通过内核在进程之间收发时,内核不对mtext域进行转换,任意的消息都可以发送。具体的转换工作时在应用程序之间进行的。但是,消息的大小,存在一个内部的限制。在Linux中,它在Linux/msg.h中的定义如下:
#define MSGMAX 8192
消息的总大小不能超过8192个字节,这其中包括mtype成员,它的长度是4个字节(long类型)。
至于为什么需要这个数据结构,是因为消息队列是面向数据块的,读取数据和发送数据都是以结构体的形式进行传递,因此需要我们自己定义数据结构,面向数据块也是消息队列的一个重要特性。

结构msqid_ds
内核msqid_ds结构—IPC对象分3类,每一类都有一个内部数据结构,该数据结构是由内核维护的。对于消息队列而言,它的内部数据结构是msqid_ds结构。对于系统上创建的每个消息队列,内核均为其创建,存储和维护该结构的一个实例。该结构在Linux/msg.h中定义,如下所示:
在这里插入图片描述
为了叙述的完整性,对每一个成员都给出一个简短的介绍:
(1)msg_perm:它是ipc_perm结构的一个实例,ipc_perm结构是在Linux/msg.h中定义的。用于存放消息队列的许可权限信息,其中包括访问许可信息,以及队列创建者的有关信息(如uid等)。
(2)msg_stime:发送到队列的最后一个消息的时间戳。(time_t)
(3)msg_rtime:从队列中获得最后一个消息的时间戳。
(4)msg_ctime:对队列进行最后一次变动的时间戳。
(5)msg_cbytes:在队列上所驻留的字节总数(即所有消息的大小的总和)
(6)msg_qnum:当前处于队列中的消息数目
(7)msg_qbytes:队列中能容纳的字节的最大数目
(8)msg_lspid:发送最后一个消息进程的PID
(9)msg_lrpid:接收最后一个消息进程的PID

结构ipc_perm
内核把IPC对象的许可权限信息存放在IPC_perm类型的结构中,例如在前面描述的某个消息队列的内部结构中,msg_perm成员就是ipc_perm类型的,它的定义是在文件<linux/ipc.h>中,如下
在这里插入图片描述
这个结构描述的书要是一些底层的东西,简单介绍如下:
(1)key:key参数用于区分消息队列
(2)uid:消息队列用户的ID号
(3)gid:消息队列用户的组ID号
(4)cuid:消息队列创建者的ID号
(5)cgid:消息队列创建者的组ID号
(6)mode:权限,用户控制读写,例如0666,可以对消息进行读写操作
(7)seq:序列号

内核中的消息队列关系
作为IPC的消息队列,其消息的传递是通过LInux内核在进行的,图中的结构成员与用户空间的表述基本一致,在消息的发送和接受的时候,内核通过一个比较巧妙的设置来实现消息插入队列的动作和从消息中查找消息的算法。
结构list_head形成一个链表,从而结构msg_msg之中的m_list成员是有个struct list_head类型的变量,通过此变量,消息形成了一个链表,在查找和插入时,对m_list域进行偏移操作就可以找到对应的消息具体位置。内核中的代码在头文件<linus/msg.h>和<linux/msg.c>中,主要的实现时插入消息和取出消息的操作。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值