这篇文章主要讲解了“Linux中消息队列的使用方式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux中消息队列的使用方式”吧!
1 消息队列的概念及使用过程
1)消息队列的概念
消息队列就是一个消息的链表。一条消息可以看作一个数据记录,此数据具有特定的格式。
进程可以按照特定的规则向队列中添加(写入)消息;其他的进程则可以从消息队列中读走消息。
2)消息队列的应用场景
消息队列本身就是IPC通信中的内容,所以它主要用于进程间的通信。
消息有读写,所以发送的消息可以用于动作的通知信号,也可以接收数据然后做其他处理。
2 消息队列相关的结构及函数
0)消息队列相关的结构
每个队列都有一个msqid_ds结构与其相关联,结构如下。
struct msqid_ds { struct ipc_perm msg_perm; // 消息队列的存取权限以及其他一些信息 time_t msg_stime; // 最近一次队列接受消息的时间 time_t msg_rtime; // 最近一次从队列中取出消息的时间 time_t msg_ctime; // 最近一次队列发生改动的时间 unsigned long __msg_cbytes; // 队列中消息的占用内存的字节数 msgqnum_t msg_qnum; // 队列中当前的消息数 msglen_t msg_qbytes; // 队列所占用内存的最大字节数 pid_t msg_lspid; // 最近一次向队列发送消息的进程的pid msgsnd pid_t msg_lrpid; // 最近一次从队列中取出消息的进程的pid };
struct ipc_perm { key_t key; ushort uid; // 用户id,有效的用户ID和有效的组id(euid和egid) ushort gid; ushort cuid; // 创建者的euid和egid ushort cgid; ushort mode; // 访问模式参见模式标志 ushort seq; // IPC对象使用频率信息 };
1)msgget函数
msgget函数用于创建或打开消息队列。
① 函数原型。
int msgget(key_t key,int msgflg)
② 头文件。
include <sys/ipc.h> include <sys/msg.h> include <sys/types.h>
③ 参数。
key:键值。
msgflg:打开标志。IPC_CREAT:表明新创建的一个消息队列。
④ 返回值。
成功:返回消息队列的id。
失败:-1。
2)msgsnd函数
msgsnd函数用于发送消息,即写消息到消息队列。
① 函数原型。
int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
② 头文件。
include <sys/ipc.h> include <sys/types.h> include <sys/msg.h>
③ 参数。
msgid:消息队列的id。
msgp:指向要发送的消息。
msgsz:消息的长度。
msgflg:标志位。
④ 返回值。
成功:0。
失败:-1。
3)msgrcv函数
msgrcv函数用于读消息队列,即从消息队列接收消息。
① 函数原型。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,intmsgflg)
② 头文件。
#include <sys/ipc.h> #include <sys/types.h> #include <sys/msg.h>
③ 参数。
msqid:消息队列的id。
msgp:存放消息。
msgsz:希望取到的消息的最大长度。
msgtyp:消息的类型,分下面三种情况:
当 msgtyp = 0:忽略类型,直接取队列中的第一条消息。
当 msgtyp > 0: 取消息队列中类型等于msgtyp的第一条消息。
当 msgtyp < 0: 取类型比msgtyp的绝对值要小或等于的消息,如果有多条消息
满足该条件,取类型最小的一条。
④ 返回值。
成功:实际接收到的消息的数据长度。
失败:-1。
4)msgctl函数
msgctl函数用于操作消息队列,比如进行消息队列的删除等等。
① 函数原型。
int msgctl(int msqid,int cmd,struct msqid_ds *buf)
② 头文件。
#include <sys/ipc.h> #include <sys/msg.h> #include <sys/types.h>
③ 参数。
msqid:消息队列的id。
cmd:消息队列的操作命令,此参数指定对msqid指定的队列要执行的命令。
IPC_STAT:取此队列的msqidds结构,并将它存放在buf指向的结构中。
IPCSET:将字段msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes从buf指向的结构复制到与这个队列相关的msqid_ds结构中。
此命令只能由下列两种进程执行:
一种是其有效用户ID等于msg_perm.cuid或msg perm.uid。
另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。
IPC_RMID:从系统中删除该消息队列以及仍在该队列中的所有数据。这种删除立即生效。
仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将得到EIDRM错误。
此命令只能由下列两种进程执行:
一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid。
另一种是具有超级用户特权的进程。这3条命令(IPC_STAT、IPC_SET和IPC_RMID)也可用于信号量和共享存储。
buf:获取内核中的msqid_ds结构,通常不用。
④ 返回值。
成功:0。
失败:-1。
3 实例代码
下面用两个进程,给大家演示下消息队列的使用过程。
实例代码如下,说明都在代码注释中了,图片。
SendQueue.c。
#include<stdio.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> #include<string.h> // 消息结构体 struct msg { long msgtype; //消息的类型 char msgtext[1024]; //消息的长度 }; void main(int argc, char *argv[]) { int msgid; char str[256]; struct msg msgst; key_t key = ftok("/tmp",600); //创建消息队列 msgid = msgget(key,0666 | IPC_CREAT); //键盘输入消息 while(1) { //获取消息数据 printf("\nPlease enter a message to send,input 'end' to quit!\n\n"); scanf("%s",str); strcpy(msgst.msgtext,str); if(strncmp(str, "end", 3) == 0) { printf("\n"); break; } //发送消息 msgsnd(msgid,&msgst,sizeof(struct msg),0); } //输出消息队列 msgctl(msgid,IPC_RMID,0); }
ReceiveQueue.c。
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> // 消息结构体 struct msg { long msgtype; char msgtext[1024]; }; int main(int argc, char *argv[]) { int RunFlag = 1; // 循环标志 int msgid = -1; // 消息id long msgtp = 0; // 消息类型 struct msg msgst; // 消息结构体变量 key_t key = ftok("/tmp",600); // 创建一个键值 msgid = msgget(key, 0666 | IPC_CREAT); //建立消息队列 if(msgid == -1) { exit(1); // 异常退出 } while(RunFlag) // 从队列中获取消息,直到遇到end消息为止 { if(msgrcv(msgid,&msgst,sizeof(struct msg), msgtp, 0) == -1) { exit(1); // 异常退出 } printf("\nThe message received is: %s\n\n",msgst.msgtext); if(strncmp(msgst.msgtext, "end", 3) == 0) // 遇到end结束 { RunFlag = 0; // 置退出循环标志 } } if(msgctl(msgid, IPC_RMID, 0) == -1) // 删除消息队列 { exit(1); // 异常退出 } exit(0); // 正常退出 }
编译程序,先运行接收程序,再运行发送程序,输入要发送的消息,退出输入end。
① 两个终端运行结果如下:
② 单个终端运行结果如下:
感谢各位的阅读,以上就是“Linux中消息队列的使用方式”的内容了,经过本文的学习后,相信大家对Linux中消息队列的使用方式这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。