首页 > 系统相关 >无涯教程-进程 - 消息队列

无涯教程-进程 - 消息队列

时间:2023-08-27 10:37:17浏览次数:37  
标签:教程 队列 无涯 int 消息 include buf mtext

使用消息队列的通信可以通过以下方式进行:

  • 通过一个进程写入共享内存,并通过另一个进程从共享内存读取。我们知道,读取也可以通过多个进程完成。

Message Queue
  • 由具有不同数据包的一个进程写入共享内存,并由多个进程(即根据消息类型)从共享内存中读取。

Multiple Message Queue

看完消息队列上的某些信息后,现在该检查支持消息队列的系统调用(System V)。

要使用消息队列执行通信,请执行以下步骤-

步骤1  -  创建消息队列或连接到已存在的消息队列(msgget())

步骤2  -  写入消息队列(msgsnd())

步骤3  -  从消息队列中读取(msgrcv())

步骤4  -  对消息队列(msgctl())执行控制操作

现在,让我们检查上述调用的语法和某些信息。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg)

该系统调用创建或分配系统V消息队列。以下参数需要传递-

  • 第一个参数key:识别消息队列,密钥可以是任意值,也可以是从库函数ftok()派生的值。

  • 第二个参数shmflg:指定所需的消息队列标志,例如IPC_CREAT(如果不存在则创建消息队列)或IPC_EXCL(与IPC_CREAT一起使用以创建消息队列,如果消息失败,则调用失败)。还需要传递权限。

该调用将在成功时返回有效的消息队列标识符,在失败的情况下返回-1。要知道失败的原因,请使用errno变量或perror()函数进行检查。

与此相关的各种错误包括EACCESS(拒绝权限),EEXIST(无法创建已经存在的队列),ENOENT(没有队列),ENOMEM(没有足够的内存来创建队列)等。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg)

此系统调用将消息发送/追加到消息队列(系统V)。以下参数需要传递-

  • 第一个参数msgid识别消息队列,即消息队列标识符, msgget()成功后将接收到标识符值

  • 第二个参数msgp是指向发送到调用方的消息的指针,该消息的格式如下-

struct msgbuf {
   long mtype;
   char mtext[1];
};

变量mtype用于与不同的消息类型进行通信,这在msgrcv()调用中进行了详细说明,变量mtext是一个数组或其他结构,其大小由msgsz(正值)指定。如果未提及多行文本字段,则将其视为零大小消息,这是允许的。

  • 第三个参数msgsz是消息的大小(消息应以空字符结尾)

  • 第四个参数msgflg表示某些标志,例如IPC_NOWAIT(在队列中未找到消息时立即返回或MSG_NOERROR立即返回)

成功时此调用将返回0,失败则返回-1。要知道失败的原因,请使用errno变量或perror()函数进行检查。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgrcv(int msgid, const void *msgp, size_t msgsz, long msgtype, int msgflg)

该系统调用从消息队列(系统V)中检索消息。以下参数需要传递-

  • 第一个参数msgid识别消息队列,即消息队列标识符, msgget()成功后将接收到标识符值

  • 第二个参数msgp是从调用方收到的消息的指针。它以以下形式的结构定义-

struct msgbuf {
   long mtype;
   char mtext[1];
};

变量mtype用于与不同的消息类型进行通信,变量mtext是一个数组或其他结构,其大小由msgsz指定。如果未提及多行文本字段,则将其视为零大小消息,这是允许的。

  • 第三个参数msgsz是接收到的消息的大小(消息应以空字符结尾)

  • 第四个参数msgtype指示消息的类型-

    • 如果msgtype为0        -  读取队列中第一个收到的消息

    • 如果msgtype为+ve   -   读取类型为msgtype的队列中的第一条消息

    • 如果msgtype为-ve    -    读取最小类型小于或等于消息类型绝对值的第一条消息

  • 第五个参数msgflg表示某些标志,例如IPC_NOWAIT(当在队列中未找到消息时立即返回或MSG_NOERROR(如果超过msgsz字节则截断消息文本)

此调用将在成功时返回mtext数组中实际接收的字节数,如果失败则返回-1。要知道失败的原因,请使用errno变量或perror()函数进行检查。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msgid, int cmd, struct msqid_ds *buf)

该系统调用执行消息队列(系统V)的控制操作。以下参数需要传递-

  • 第一个参数msgid识别消息队列,即消息队列标识符, msgget()成功后将接收到标识符值

  • 第二个参数cmd是用于在消息队列上执行所需控制操作的命令。 cmd的有效值为-

            IPC_STAT    -   将结构msqid_ds的每个成员的当前值的信息复制到buf指向的传递结构。此命令需要对消息队列具有读取权限。

            IPC_SET       -  设置结构buf指向的用户ID,所有者的组ID,权限等。

            IPC_RMID   -  立即删除消息队列。

            IPC_INFO   -  返回有关由buf指向的结构类型为msginfo的消息队列限制和参数的信息

            MSG_INFO-  返回一个msginfo结构,该结构包含有关消息队列消耗的系统资源的信息。

  • 第三个参数buf是指向名为struct msqid_ds的消息队列结构的指针。此结构的值将用于按cmd设置或获取。

该调用将根据传递的命令返回该值。 IPC_INFO和MSG_INFO或MSG_STAT成功返回消息队列的索引或标识符,对于其他操作返回0,在失败的情况下返回-1。要知道失败的原因,请使用errno变量或perror()函数进行检查。

看完有关消息队列的基本信息和系统调用之后,现在该检查程序了。

让我们在看程序之前先看一下描述-

步骤1  -  创建两个进程,一个用于发送到消息队列(msgq_send.c),另一个用于从消息队列中检索(msgq_recv.c)

步骤2  -  使用ftok()函数创建密钥。为此,最初将创建文件msgq.txt以获取唯一密钥。

步骤3 -  发送进程执行以下操作。

  • 读取用户输入的字符串

  • 删除新行(如果存在)

  • 发送到消息队列

  • 重复该进程直到输入(CTRL + D)结束

  • 接收到输入结束后,发送消息" end"以表示进程结束

步骤4 -  在接收进程中,执行以下操作。

  • 从队列中读取消息
  • 显示输出
  • 如果收到的消息是"end",请完成该进程并退出

为简化起见,我们不在此示例中使用消息类型。同样,一个进程正在写入队列,而另一个进程正在从队列读取。可以根据需要扩展它,即,理想情况下,一个进程将写入队列,而多个进程则从队列中读取。

现在,让我们检查进程(消息发送到队列中)–文件:msgq_send.c

/* Filename: msgq_send.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define PERMS 0644
struct my_msgbuf {
   long mtype;
   char mtext[200];
};

int main(void) {
   struct my_msgbuf buf;
   int msqid;
   int len;
   key_t key;
   system("touch msgq.txt");
   
   if ((key = ftok("msgq.txt", 'B')) == -1) {
      perror("ftok");
      exit(1);
   }
   
   if ((msqid = msgget(key, PERMS | IPC_CREAT)) == -1) {
      perror("msgget");
      exit(1);
   }
   printf("message queue: ready to send messages.\n");
   printf("Enter lines of text, ^D to quit:\n");
   buf.mtype = 1; /* we don't really care in this case */
   
   while(fgets(buf.mtext, sizeof buf.mtext, stdin) != NULL) {
      len = strlen(buf.mtext);
      /* remove newline at end, if it exists */
      if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
      if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */
      perror("msgsnd");
   }
   strcpy(buf.mtext, "end");
   len = strlen(buf.mtext);
   if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */
   perror("msgsnd");
   
   if (msgctl(msqid, IPC_RMID, NULL) == -1) {
      perror("msgctl");
      exit(1);
   }
   printf("message queue: done sending messages.\n");
   return 0;
}

编译和执行步骤

message queue: ready to send messages.
Enter lines of text, ^D to quit:
this is line 1
this is line 2
message queue: done sending messages.

以下是消息接收进程中的代码(从队列中检索消息)–文件:msgq_recv.c

/* Filename: msgq_recv.c */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define PERMS 0644
struct my_msgbuf {
   long mtype;
   char mtext[200];
};

int main(void) {
   struct my_msgbuf buf;
   int msqid;
   int toend;
   key_t key;
   
   if ((key = ftok("msgq.txt", 'B')) == -1) {
      perror("ftok");
      exit(1);
   }
   
   if ((msqid = msgget(key, PERMS)) == -1) { /* connect to the queue */
      perror("msgget");
      exit(1);
   }
   printf("message queue: ready to receive messages.\n");
   
   for(;;) { /* normally receiving never ends but just to make conclusion 
             /* this program ends wuth string of end */
      if (msgrcv(msqid, &buf, sizeof(buf.mtext), 0, 0) == -1) {
         perror("msgrcv");
         exit(1);
      }
      printf("recvd:\"%s\"\n", buf.mtext);
      toend = strcmp(buf.mtext,"end");
      if (toend == 0)
      break;
   }
   printf("message queue: done receiving messages.\n");
   system("rm msgq.txt");
   return 0;
}

编译和执行步骤

message queue: ready to receive messages.
recvd: "this is line 1"
recvd: "this is line 2"
recvd: "end"
message queue: done receiving messages.

参考链接

https://www.learnfk.com/process/inter-process-communication-message-queues.html

标签:教程,队列,无涯,int,消息,include,buf,mtext
From: https://blog.51cto.com/u_14033984/7250808

相关文章

  • windows10下SQL Prompt安装图文教程
    一、下载安装官网或者教程:www.red-gate.comvs可以去插件库       二、激活失效激活失效:方法1:在本地hosts加入以下代码:127.0.0.1licensing.red-gate.com127.0.0.1www.red-gate.com127.0.0.1red-gate.com127.0.0.1productusage.red-gate.com127.0.......
  • shell简明教程2退出状态和返回代码
    2退出状态和返回代码在本章中,您将学习如何确定给定命令的退出状态。还将学习如何在脚本中根据不同命令的退出状态做出决定。最后,还将学习如何在自己的脚本中使用退出状态。每次执行命令都会返回一个退出状态。退出状态有时也称为返回代码或退出代码,是范围从0到255的整数。按......
  • 无涯教程-进程 - 管道(Pipes)
    管道是两个或多个相关进程之间的通信介质,它可以在一个进程内,也可以在子进程与父进程之间进行通信。可以实时查看管道机制,例如用管道将水填充到某个容器(例如桶)中,然后取回某人(例如用杯子)。填充进程只不过是写入管道,而读取进程只不过是从管道中检索,这意味着一个输出(水)被输入......
  • Cinema 4D Download Install资源及使用教程
    Cinema4Dr25是一款专业的3D建模、动画、模拟和渲染软件解决方案,该软件其快速、强大、灵活和稳定的工具集使设计、运动图形、VFX、AR/MR/VR、游戏开发和所有类型的可视化专业人士更容易和高效地使用3D工作流程。使用它,哪怕是像制作动物毛发这样十分精细的三维特效也是可以轻轻......
  • 无涯教程-进程 - 其它进程
    到目前为止,我们已经讨论了进程,进程的创建,父进程和子进程等。如果不讨论其他相关进程(如孤立进程,僵尸进程和守护进程),则将是不完整的。孤立进程当我们运行程序或应用程序时,该应用程序的父进程是shell,当我们使用fork()创建进程时,新创建的进程是子进程,而创建子进程的进程是父进程......
  • [Python] PyCharm(Python IDE)安装教程
    1简介PyCharm是目前最流行、使用最广泛的PythonIDE(IntegratedDevelopmentEnvironment,集成开发环境),带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。比如调试、语法高亮、项目管理、代码跳转、智能提示、单元测试、版本控制等。此外,还提供了一些高级功能,以......
  • 无涯教程-进程 - 创建&终止
    到现在为止,我们知道无论何时执行程序,都会创建一个进程,并且该进程将在执行完成后终止,如果我们需要在程序中创建一个进程,并且可能希望为其安排其他任务,该怎么办。能做到吗?是的,显然是通过进程创建的,当然,工作完成后,它将自动终止,或者您可以根据需要终止它。进程创建是通过fork()系......
  • 求生之路2私人服务器开服搭建教程centos
    求生之路2私人服务器开服搭建教程centos大家好我是艾西,朋友想玩求生之路2(left4dead2)重回经典。Steam玩起来有时候没有那么得劲,于是问我有没有可能自己搭建一个玩玩。今天跟大家分享的就是求生之路2的自己用服务器搭建的一个心路历程。(因平台原因本文中www即为xxx,com即为zzz,http/......
  • 求生之路2社区服务器sourcemod安装配置搭建教程centos
    求生之路2社区服务器sourcemod安装配置搭建教程centos大家好我是艾西,通过上文我们已经成功搭建了求生之路2的服务端。但是这个服务端是纯净的服务端,就是那种最纯粹的原版。如果想要实现插件、sm开头的命令等功能,需要安装这个sourcemod。那本篇文章给搭建简单的说下sourcemod安装以......
  • Stable Diffusion web UI 部署详细教程
    前言本文使用AutoDL平台进行StableDiffusionwebUI云端部署AutoDL官网:[AutoDL算力云|弹性、好用、省钱。租GPU就上AutoDL]StableDiffusionwebUI官网:AUTOMATIC1111/stable-diffusion-webui:StableDiffusionwebUI(github.com)步骤租用实例选择社区镜像AUTOM......