什么是音讯队列?
假如你是一个快递员,你须要将货物从一个仓库运到另一个仓库。然而你发现自己的工夫不够用,须要另外请一个人来帮忙。那么,你们之间如何进行合作呢?
一种形式是间接将货物全副交给对方,但这样存在危险:对方可能会呈现问题,导致货物失落或损坏。
而另一种更平安的形式是,你将货物分批发送给对方,对方再依照你的要求逐批接管货物。这种形式相似于音讯队列的通信形式。
在 Linux 零碎中,音讯队列是一种 IPC(过程间通信)机制,用于实现不同过程之间的通信。
简略地说,音讯队列是一个音讯的链表,音讯发送方将音讯发送到音讯队列中,音讯接管方从队列中读取音讯。
音讯队列的长处和毛病
与其余 IPC 机制相比,音讯队列有以下长处:
- 通过音讯队列能够实现异步通信。
- 音讯队列能够存储多个音讯,接管方能够按程序一一读取音讯。
- 音讯队列的音讯长度能够很长。
然而,音讯队列也有以下毛病:
- 音讯队列的音讯长度有限度,个别不能超过零碎限度的最大值。
- 音讯队列须要调用非凡的零碎调用来读写音讯,开销较大。
音讯队列的创立和应用办法
在Linux中,能够通过以下零碎调用函数来创立和应用音讯队列:
#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int msgflg); // 创立或关上音讯队列int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); // 向音讯队列发送音讯ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); // 从音讯队列接管音讯int msgctl(int msqid, int cmd, struct msqid_ds *buf); // 管制音讯队列
其中,key
是用来惟一标识音讯队列的键值,msgflg
是创立音讯队列时的选项参数。在创立音讯队列时,如果该键值曾经存在,则间接返回该音讯队列的标识符;如果不存在,则创立一个新的音讯队列,并返回该音讯队列的标识符。
在应用音讯队列时,msgsnd
函数用于向音讯队列中发送音讯,msgrcv
函数用于从音讯队列中接管音讯,msgctl
函数用于对音讯队列进行管制,比方删除音讯队列等。
音讯队列的发送和接管示例
上面咱们来看一个简略的示例,展现如何应用音讯队列进行过程间通信。
假如有两个过程,一个发送过程和一个接管过程,它们之间须要传递一些数据。咱们通过音讯队列来实现过程间通信。
首先,咱们须要创立一个音讯队列,而后让发送过程向音讯队列中发送一条音讯,接管过程从音讯队列中接管该音讯,并进行解决。
创立音讯队列
咱们首先须要创立一个音讯队列。能够应用msgget
函数来创立音讯队列。以下是创立音讯队列的示例代码:
#include <sys/msg.h>#include <stdio.h>#include <stdlib.h>int main(){ key_t key = ftok("/tmp", 'a'); // 创立一个惟一的key int msgid = msgget(key, 0666 | IPC_CREAT); // 创立音讯队列 if (msgid == -1) { perror("msgget"); exit(EXIT_FAILURE); } printf("音讯队列创立胜利,msgid=%d\n", msgid); return 0;}
在下面的代码中,咱们应用ftok
函数创立一个惟一的key,这个key将作为音讯队列的标识符。而后,咱们应用msgget
函数创立音讯队列。如果创立胜利,msgget
函数将返回一个音讯队列ID(msgid),否则将返回-1。在本例中,如果创立音讯队列失败,咱们将输入谬误音讯并退出程序。
发送音讯
接下来,咱们将应用msgsnd
函数向音讯队列发送一些音讯。以下是一个发送音讯的示例代码:
// sendmsg.c#include <sys/msg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct { long type; char text[100];} message_t;int main(){ key_t key = ftok("/tmp", 'a'); // 创立一个惟一的key int msgid = msgget(key, 0666 | IPC_CREAT); // 创立音讯队列 if (msgid == -1) { perror("msgget"); exit(EXIT_FAILURE); } message_t message; message.type = 1; strcpy(message.text, "Hello, World!"); int result = msgsnd(msgid, &message, sizeof(message.text), 0); if (result == -1) { perror("msgsnd"); exit(EXIT_FAILURE); } printf("音讯发送胜利,text=%s\n", message.text); return 0;}
在下面的代码中,咱们定义了一个message_t
构造体,它蕴含一个长整型变量和一个字符串数组。长整型变量将用于指定音讯类型,而字符串数组将蕴含音讯注释。而后,咱们应用msgsnd
函数将音讯发送到队列。在本例中,咱们发送的音讯类型为1,音讯注释为"Hello, World!"。
接管音讯
最初,咱们将应用msgrcv
函数从音讯队列接管咱们之前发送的音讯。以下是一个接管音讯的示例代码:
// rsvmsg.c#include <sys/msg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct { long type; char text[100];} message_t;int main(){ key_t key = ftok("/tmp", 'a'); // 创立一个惟一的key int msgid = msgget(key, 0666 | IPC_CREAT); // 创立音讯队列 if (msgid == -1) { perror("msgget"); exit(EXIT_FAILURE); } message_t message; int result = msgrcv(msgid, &message, sizeof(message.text), 1, 0); if (result == -1) { perror("msgrcv"); exit(EXIT_FAILURE); } printf("音讯接管胜利,text=%s\n", message.text); return 0;}
成果演示
编译下面的sendmsg.c 和 rsvmsg.c文件,失去一个两个程序:sendmsg和rsvmsg。
- 先运行sendmsg,后运行rsvmsg
[wayne@wayne:~] ./sendmsg音讯发送胜利,text=Hello, World!
[wayne@wayne:~] ./rsvmsg音讯接管胜利,text=Hello, World!
- 先运行rsvmsg,后运行sendmsg
[wayne@wayne:~] ./rsvmsg
此时rsvmsg会阻塞在这里,期待音讯
[wayne@wayne:~] ./sendmsg音讯发送胜利,text=Hello, World!
sendmsg发送音讯后,rsvmsg过程,收到音讯,打印消息
音讯接管胜利,text=Hello, World!
小结
总的来说,Linux 音讯队列是一种高效的过程间通信机制,它能够在多个过程之间共享,容许过程异步地发送和接管音讯。
以上,如果感觉对你有帮忙,点个赞再走吧,这样@知微之见也有更新上来的能源!
也欢送私信我,一起交换!