在Linux中,IPC消息队列是一个双向通信的全内存设计,即内核保证了读写顺序和数据同步,并且是性能比较好的先进先出的数据结构。消息队列的应用场景:比如异步任务处理,抢占式的数据分发,顺序缓存区等。
消息队列的产生原因
消息队列其实就是消息传输过程中保存消息的容器,既然有了管道,为什么要出现消息队列呢?理由如下:
(1)生命周期:匿名管道和命名管道都是随进程的,意味着管道的生命周期是随进程的退出而退出的。
(2)传送方式:管道传送数据时以无格式字节流的形式传送,给程序的开发带来不便。
(3)信号传递量:担当数据传送媒介的管道,其缓冲区大小受到较大的限制。
鉴于上面的三种原因:IPC方式下的另一种进程间通信——>消息队列应运而生。它克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
什么是消息队列?
[普通定义]:消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法,每个数据块都被认为含有一个类型,接受者接受的数据块可以有不同的类型值,我们可以通过发送消息来避免命名管道的同步和阻塞问题。
[最佳定义]:内核地址空间中的内部链表,消息可以顺序地发送到队列中,并以几种不同的方式从队列中获取,每个消息队列是由IPC标识符所唯一标识的。
消息队列与管道的不同在于:消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出,而且如果你没有显示的删除它,那么在关机之前它一直存在。
消息队列的上限
消息队列与管道也是一样的不足,就是每个消息队列的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限(MSGMNB),系统上消息队列的总数也是有一个上限(MSGMNI)。
[root@localhost panpan]# cat /proc/sys/kernel/msgmax
65536 //每个消息的最大长度
[root@localhost panpan]# cat /proc/sys/kernel/msgmnb
65536 //每个消息队列的总的字节数
[root@localhost panpan]# cat /proc/sys/kernel/msgmni
1735 //系统消息队列的总数
IPC对象数据结构
内核为每个IPC对象维护了一个数据结构(存在于/usr/include/linux/ipc.h)
struct ipc_perm
{
__kernel_key_t key;//端口号
__kernel_uid_t uid;//所有者的用户ID
__kernel_gid_t gid;//所有者组ID
__kernel_uid_t cuid;//创建者的用户ID
__kernel_gid_t cgid;//创建者的组ID
__kernel_mode_t mode; //访问模式
unsigned short seq;//顺序值
};
不仅如此,消息队列,共享内存和信号量都有这样一个共同的数据结构。
消息队列结构
消息队列结构存在于/usr/include/linux/msg.h目录下:
struct msqid_ds {
struct ipc_perm msg_perm; /* IPC对象结构体 */
struct msg *msg_first; /*消息队列头指针*/
struct msg *msg_last; /*消息队列尾指针*/
__kernel_time_t msg_stime; /*最后一次插入消息队列消息的时间*/
__kernel_time_t msg_rtime; /*最后一次接收消息即删除队列中一个消息的时间*/
__kernel_time_t msg_ctime; /* 最后修改队列的时间*/
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes;