消息队列是在两个进程之间传递二进制数据的一种简单有效的方式 。每个数据块都有一个特定的类型,接收方可以根据类型来有选择地接受数据,而不一定像管道和命名管道那样必须以先进先出的方式接受数据 。
linux消息队列的API都定义在sys/msg.h头文件中,包括4个系统调用:msgget、msgsnd、msgrcv、msgctl
msgget系统调用msgget系统调用创建一个消息队列,或者获取一个已有的消息队列 。定义如下:
#include <sys/msg.h>int msgget(key_t key, int msgflg);
和semegt系统调用一下,key参数是一个键值,用来标识一个全局唯一的消息队列 。
msgflg参数使用的含义与semget系统调用的sem_flags参数相同 。
(多进程编程 - 信号量)
msgget成功时返回一个正整数值,它是消息队列u的标识符 。msgget失败时返回-1,并设置errno 。
如果msgget用于创建消息队列,则与之关联的内核数据结构msqid_ds将被创建并初始化,msqid_ds结构体的定义如下:
sturct msqid_ds{struct ipc_perm msg_perm;/*消息队列的操作权限*/time_t msg_stime;/*最后一次调用msgsnd时间*/time_t msg_rtime;/*最后一次调用msgrcv时间*/time_t msg_ctime;/*最后一次被修改的时间*/unsigned long __msg_cbytes; /*消息队列中已有的字节数*/msgqnum_t msg_qnum;/*消息队列中已有的消息数*/msglen_t msg_qbytes;/*消息队列允许的最大字节数*/pid_t msg_lspid;/*最后执行msgsnd的进程的PID*/pid_t msg_lrpid;/*最后执行msgrcv的进程的PID*/};
msgsnd系统调用msgsnd系统调用把一条消息添加到消息队列中 。定义如下:
#include <sys/msg.h>int msgsnd(int msqid, const void* msg_ptr, size_t msg_sz, int msgflg);
msqid参数是由msgget调用返回的消息队列标识符
msg_ptr参数指向一个准备发送的消息,消息必须被定义为如下类型:
struct msgbuf{long mtype; //消息类型char mtext[512]; //消息数据};
其中:
- mtype成员指定消息的类型,它必须是一个正整数 。
- mtext是消息数据
msgflg参数空值msgsnd的行为,它通常仅支持IPC_NOWAIT标志,即非阻塞的方式发送消息 。默认情况下,发送消息时如果消息队列满了,则msgsnd将阻塞 。
若IPC_NOWAIT标志被指定,则msgsnd将立即返回并设置errno为EAGAIN 。
【多进程编程 - 消息队列】处于阻塞状态的msgsnd调用可能被如下两种异常情况所中断:
- 消息队列被移除 。此时msgsnd调用将立即返回并设置errno为EIDRM
- 程序接收到信号 。此时msgsnd调用将立即返回并设置errno为EINTR
- 将msg_qnum加1
- 将msg_lspid设置为调用进程的PID
- 将msg_stime设置为当前的时间
#include <sys/msg.h>int msgrcv(int msqid, void* msg_ptr,size_t msg_sz,long int msgtype, int msgflg);
msqid参数是由msgget调用返回的消息队列标识符msg_ptr参数用于存储接受的消息,msg_sz参数指定的是消息数据部分的长度
msgtype参数指定接受何种类型的消息 。有如下几种方式来指定消息类型:
- msgtype等于0 。读取消息中的第一个消息 。
- msgtype大于0 。读取消息队列中第一个类型为msgtype(除非指定了标志MSG_EXCEPT)
- msgtype小于0 。读取消息队列中第一个类型比msgtype的绝对值小的消息 。
- IPC_NOWAIT:如果消息队列中没有消息,则msgrcv调用立即返回并设置errno为ENOMSG
- MSG_EXCEPT:如果msgtype大于0,则接受消息队列中第一个非msgtype类型的消息
- MSG_NOERROR:如果消息数据部分的长度超过了msg_sz,就将它设置为EINTR
- 消息队列被移除 。此时msgrcv调用将立即返回并设置errno为EIDRM
- 程序接收到信号 。此时msgrcv调用将立即返回并设置errno为EINTR
- 将msg_qnum减1
- 将msg_lrpid设置为调用进程的PID
- 将msg_rtime设置为当前的时间
推荐阅读
- 古代皇帝儿女最多的是谁 古代有哪位皇帝只娶了一个老婆
- 君山银针茶叶会过期吗,君山银针多少钱斤君山银针品级特征
- 2021年社保个人缴费多少钱?
- 银元|家里面找出很多1分、2分、5分硬币,收藏价值怎么样呢?
- 杨贵妃有多胖多少斤 杨贵妃胖还是瘦?
- 阿诗丹顿热水器价格是多少
- 如果南明没有灭亡 南明王朝存在多少年
- 加多宝凉茶真的降火吗,中国凉茶加多宝亮相米兰世博会
- 老人冬季多晒太阳 这样的晒法最健康
- 冬季开空调多少度合适 4点事项要注意