乐趣区

关于人工智能:Linux进程通信-消息队列

什么是音讯队列?

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

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

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

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

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

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

退出移动版