Linux进程间通信——03消息队列

消息队列:

消息:数据+类型  给数据一种特殊的标志

队列:先进先出,但其类似优先级队列。

消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。每个数据块都有一个特定的类型,接收方可以根
据类型来有选择地选择接收数据,而不一定像管道和命名管道那样必须先进先出的方式接收数据。

消息队列也有和管道一样的不足,就是每个消息的最大长度是有上限的,每个消息队列的总的字节数有上限,系统上消息队列的总数也是有上限的。


函数:

头文件:#include <sys/msg.h>

1、mesget系统调用:得到消息队列标识符或创建一个消息队列对象并返回消息队列标识符。

      原型:int mesget (key_t key,int msgflg);

      参数:1)key是一个键值。输入0:会建立新消息队列。大于0的32位整数:视参数msgflg来确定操作。

                            2)与信号量semget函数参数一致。

       返回值:成功返回成功返回一个非负整数,即该消息队列的标识码;失败返回-1。

当创建完成之后,内核数据结构msqid_ds也被创建并初始化。

Linux进程间通信——03消息队列

2、msgsnd系统调用:将msg_ptr 消息写入到标识符为msqid的消息队列

      原型:int msgsnd(int msqid,const void*msg_ptr ,size_t msg_sz, int msgflag)

      参数:1)消息队列标识符  mesget函数返回值。

                            2)指向一个准备发送的消息。可以是任何类型的结构体,但第一个字段必须为long类型,msgrcv根据此长整数确定消息的类型。

msgp定义的参照格式如下:

struct s_msg
{
    long type; /* 必须大于0,消息类型 */
    char mtext[256]; /*消息正文,可以是其他任何类型*/
} msg_ptr;

                            3)要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度

                            4)0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列

                               IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回

                               IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。

       返回值:成功返回0;失败返回-1。

3、msgrcv系统调用:从标识符为msqid的消息队列读取消息并存于msg_ptr中,读取后把此消息从消息队列中删除

      原型:int msgrcv(int msqid,void*msg_ptr,size_t msg_sz,long int msgtype, int msgflg)

      参数:1)消息队列标识符。

                            2)存放消息的结构体,结构体类型要与msgsnd函数发送的类型相同。

                            3)要接收消息的大小,不含消息类型占用的4个字节。

                            4)0:接收第一个消息。

                                  >0:接收类型等于msgtyp的第一个消息。

                                  <0:接收类型等于或者小于msgtyp绝对值的第一个消息。

                            5)0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待。

                                  IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG。

                                  IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息。

                                  IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃。

       返回值:成功返回实际读取到的消息数据长度;失败返回-1

       msgrcv()解除阻塞的条件有以下三个:

                  ①    消息队列中有了满足条件的消息。②    msqid代表的消息队列被删除。③    调用msgrcv()的进程被信号中断。

4、msgctl系统调用:获取和设置消息队列的属性。

      原型:int msgctl(int msgid, int command ,struct msqid_ds*buf);

      参数:1)消息队列标识符

                            2)IPC_STAT:获得msgid的消息队列头数据到buf中

                                  IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes

                            3)buf:消息队列管理结构体,请参见消息队列内核结构说明部分

Linux进程间通信——03消息队列

       返回值:成功返回0;失败返回-1。

参考博文:https://blog.csdn.net/guoping16/article/details/6584024


Linux系统中有两个宏定义:
                     MSGMAX, 以字节为单位,定义了一条消息的最大长度。
                     MSGMNB, 以字节为单位,定义了一个队列的最大长度。

消息队列优缺点:
                     优点:

                            1、可以实现任意进程间的通信,并通过系统调用函数来实现消息发送和接收之间的同步,无需考虑同步问题,方便;

                            2、独立于进程的存在,不会像管道那样,随着进程结束而结束,它是Linux系统给的一个消息队列表,是一个链表存在。

                            3、消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点。

          缺点:信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合

消息队列应用场景:https://www.cnblogs.com/linjiqin/p/5720865.html


代码实现: