什么是音讯队列?

假如你是一个快递员,你须要将货物从一个仓库运到另一个仓库。然而你发现自己的工夫不够用,须要另外请一个人来帮忙。那么,你们之间如何进行合作呢?

一种形式是间接将货物全副交给对方,但这样存在危险:对方可能会呈现问题,导致货物失落或损坏。

而另一种更平安的形式是,你将货物分批发送给对方,对方再依照你的要求逐批接管货物。这种形式相似于音讯队列的通信形式。

在 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 音讯队列是一种高效的过程间通信机制,它能够在多个过程之间共享,容许过程异步地发送和接管音讯。

以上,如果感觉对你有帮忙,点个赞再走吧,这样@知微之见也有更新上来的能源!

也欢送私信我,一起交换!