【Linux】进程间通信之消息队列
文章目录
- 消息队列的概念
- 消息队列的出队特点
- 消息队列函数接口
- 获取消息队列
- 向消息队列发送消息
- 接收消息
- 操作消息队列的接口
- 代码演示
- ipcs命令
消息队列的概念
消息队列提供进程间数据块传输的方法,传输的每一个数据块都认为是有类型的,不同的数据块是有优先级的;
系统中可能有很多的msgqueue, 每个MQ用消息队列描述符(消息队列ID: qid) 来区分,qid是唯一 的,用来区分不同的MQ。
消息队列的出队特点
消息队列中的数据都是先进先出的,整个队列中的数据是用链表组织起来的。
消息队列的每一个元素都是有类型的,用类型可以区分不同的消息,可以按照消息类型先进先出,也可以按照原本队列的顺序先进先出
消息队列函数接口
获取消息队列
int msgget(key_t key, int msgflg);
功能:以特定的消息队列标识符创建一个消息队列,并返回消息队列的操作句柄
头文件:sys/types.h、sys/ipc.h、sys/msg.h
参数:
- key:消息队列的标识符
- msgflg:创建的标志,可以按位或上一个权限(8进制的数字):IPC_CREAT:若共享内存不存在,则创建;IPC_EXCL:与IPC_CREAT一同使用,为了确保共享内存已经存在时,会报告错误
返回值: - 成功:返回队列ID
- 失败:返回-1,并设置erron
向消息队列发送消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
- msgid:消息队列ID
- msgp:指向msgbuf的指针,用来指定发送的消息。操作系统为该函数发送的消息定义了发送格式,只是定义了一部分,另一部分要程序员自己去定义
- msgsz:要发送消息的长度,消息内容的长度,这个参数的取值并不是整个struct msgbuf结构体的大小,而是结构中mtext的大小
- msgflg:创建标记;0:阻塞发送;IPC_NOWAIT:非阻塞发送,如果指定IPC_NOWAIT,失败会立即返回
接收消息
ssize_t msgrcv(int msqid, void *msgp, sizet msgsz, long msgtyp, int msgflg)
头文件:sys/types.h、sys/ipc.h、sys/msg.h
参数:
- msqid:消息队列ID
- msgp:指向msgbuf的指针,用来接收消息(出参)
- msgsz:要接收消息的长度
注意:参数msgsz 指定由msgp 参数指向的结构的成员mtext的最大大小(以字节为单位), - msgtyp:接收消息的方式
msgtyp | 解释 |
---|---|
msgtyp = 0 | 读取队列中的第一条消息,就相当于不区分类型,按照插入的顺序,先进先出 |
msgtyp > 0 | 读取队列中类型为msgtyp 的第一条消息,除非在msgflg中指定了MSG_ EXCEPT, 否则将读取类型不等于msgtyp的第一条消息 |
msgtyp < 0 | 读取队列中类型小于或等于msgtyp 绝对值的第一条消息 |
- msgflg:创建标记;0:阻塞发送;IPC_NOWAIT:非阻塞发送,如果指定IPC_NOWAIT,失败会立即返回
返回值:
- 成功返回实际读取消息的字节数,,
- 失败返回-1,并设置erron
操作消息队列的接口
int msgctl(int msqid, int cmd, struct msqid_ ds *buf);
参数:
- msqid:消息队列ID
- cmd:控制命令,例如IPC_ RMID:删除命令 IPC STAT:获取状态
- buf:存储消息队列的相关信息的buf
返回值:
- 成功根据不同的cmd有不同的返回值,
- 失败返回-1,并设置erron
从消息队列中拿数据和从共享内存中拿数据不一样,是直接取走数据,不是拷贝走
代码演示
往消息队列中发送消息:
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/msg.h>4 struct Msgbuf{5 long mtype;6 char mtext[255];7 };8 int main(){9 /*10 * 目的:往消息队列当中发送消息11 *12 * 做法:13 * 1. 创建消息队列14 * 2. 组织要发送的消息,并且发送出去15 * 1 : send msg116 * 2 : send msg217 * 3 : send msg318 * 4 : send msg419 * ...20 * */ 21 int qid = msgget(0x78787878, IPC_CREAT | 0664);22 if(qid < 0){23 perror("msgget");24 return 0;25 }26 27 for(int i = 0; i < 10; i++){28 //i [0, 9]29 struct Msgbuf mb;30 mb.mtype = i;31 snprintf(mb.mtext, sizeof(mb.mtext), "send msg%d", i);32 msgsnd(qid, &mb, sizeof(mb.mtext), 0);33 }34 return 0;35 }
从发送队列中接收消息:
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/msg.h>4 5 struct Msgbuf{6 long mtype;7 char mtext[255];8 };9 10 int main(){11 /*12 * 目的:从消息队列当中获取消息13 *14 * 做法:15 * 1. 获取或者创建消息队列16 * 2. 调用msgrecv函数进行获取消息17 * 3. 打印获取到的消息内容18 * send msg119 * send msg220 * .... 21 *22 * 4 : send msg423 * */24 int qid = msgget(0x78787878, IPC_CREAT | 0664);25 if(qid < 0){26 perror("msgget");27 return 0; 28 }29 struct Msgbuf mb;30 31 msgrcv(qid, &mb, sizeof(mb.mtext), 5, 0); // send msg532 printf("%s\n", mb.mtext);33 msgrcv(qid, &mb, sizeof(mb.mtext), 6, 0); // send msg634 printf("%s\n", mb.mtext);35 msgrcv(qid, &mb, sizeof(mb.mtext), 7, 0); // send msg736 printf("%s\n", mb.mtext);37 return 0;38 }
执行结果:
ipcs命令
用该命令查看一下:
ipcrm -q [qid] 可删除消息队列
消息队列的生命周期跟随操作系统内核