当前位置: 首页 > news >正文

Linux系统编程之消息队列

概述

        消息队列是一种进程间通信机制,允许不同的进程通过发送和接收消息来进行数据交换。实际上,消息队列是一种基于队列的数据结构,用于存储多个消息。每个消息由一个类型和相应的数据组成,类型可以用来区分不同类型的消息或优先级。

        消息队列的主要优势包括如下三点。

        1、灵活性。支持多种消息类型,可以根据需要定义不同类型的消息。

        2、可靠性。消息不会丢失,即使发送者和接收者不在同一时间运行,消息也会被保存在队列中直到被处理。

        3、异步通信。发送者和接收者不需要同时在线,消息可以在任何时间点被发送或接收。

        在Linux系统中,消息队列主要通过POSIX标准接口和System V IPC接口来实现。

POSIX消息队列

        POSIX消息队列基于POSIX标准,提供了比System V消息队列更简单的接口,并且可以在文件系统中作为一个特殊的文件节点来访问。POSIX消息队列可以通过一个路径名来标识,这使得不同的进程可以使用这个路径名来访问同一个消息队列。当消息队列的状态改变时(比如:消息队列从空变为非空),可以向指定的进程发送异步通知。POSIX消息队列适用于那些需要进程间高效、可靠通信的应用场景,由于它支持优先级排队和异步通知等特性,特别适合实时系统中的应用。

        POSIX消息队列主要通过以下函数来实现。

        mq_open:创建一个新的消息队列,或打开一个已经存在的消息队列。

        mq_send:将一条消息放入到消息队列中。

        mq_receive:从消息队列中接收消息。

        mq_close:关闭消息队列。

        mq_unlink:删除消息队列的名字,使其他进程无法再访问该消息队列。

        在下面的实战代码中,我们通过POSIX消息队列在两个进程之间发送和接收消息。

        首先,我们创建了一个接收者进程,用于打开消息队列,并接收消息。

#include <fcntl.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define QUEUE_NAME         "/queue_hope"int main()
{// 初始化属性struct mq_attr attr;attr.mq_flags = 0;attr.mq_maxmsg = 10;attr.mq_msgsize = 1024;attr.mq_curmsgs = 0;// 打开消息队列mqd_t mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr);if (mq == (mqd_t)-1){printf("mq_open failed\n");return -1;}// 接收消息char pszBuf[1024] = {0};unsigned int prio = 0;ssize_t bytes_read = mq_receive(mq, pszBuf, sizeof(pszBuf), &prio);if (bytes_read >= 0){printf("Recv message: '%s' with priority %u\n", pszBuf, prio);}else{printf("mq_receive failed\n");}// 关闭并删除消息队列mq_close(mq);mq_unlink(QUEUE_NAME);return 0;
}

        接下来,我们创建了一个发送者进程,用于发送消息到之前定义的消息队列。

#include <fcntl.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define QUEUE_NAME         "/queue_hope"int main()
{// 打开已存在的消息队列mqd_t mq = mq_open(QUEUE_NAME, O_WRONLY);if (mq == (mqd_t)-1){printf("mq_open failed\n");return -1;}// 发送消息char pszBuf[] = "Hello, Hope_Wisdom";unsigned int prio = 1;if (mq_send(mq, pszBuf, strlen(pszBuf), prio) != 0){printf("mq_send failed\n");}// 关闭消息队列mq_close(mq);return 0;
}

System V消息队列

        由于其设计较早,System V消息队列可能在某些方面不如POSIX消息队列高效,特别是在现代实时应用中。System V消息队列提供了较为复杂的API,这些函数提供了对消息队列更细致的控制,但也意味着更高的学习成本和实现复杂度。System V消息队列支持发送不同类型的消息,并允许接收方根据消息类型选择性地接收消息。每个消息都必须指定一个类型(大于0的整数),这为消息过滤提供了灵活性。

        System V消息队列主要通过以下函数来实现。

        msgget:获取一个消息队列的标识符,如果不存在则创建一个新的。

        msgsnd:向指定的消息队列发送一条消息。

        msgrcv:从指定的消息队列接收一条消息。

        msgctl:执行多种控制操作,如获取消息队列属性、设置消息队列属性、删除消息队列等。

        在下面的实战代码中,我们通过System V消息队列在两个进程之间发送和接收消息。

        首先,我们创建了一个接收者进程,用于打开消息队列,并接收消息。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>struct message
{long mtype;char mtext[100];
};int main()
{// 创建唯一的键key_t key = 0;if ((key = ftok("progfile", 66)) == -1){printf("ftok failed\n");return -1;}// 获取消息队列IDint msgid;if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1){printf("msgget failed\n");return -1;}// 接收消息struct message msg;if (msgrcv(msgid, &msg, sizeof(msg), 1, 0) == -1){printf("msgrcv failed\n");return -1;}printf("Recv Message: %s\n", msg.mtext);return 0;
}

        接下来,我们创建了一个发送者进程,用于发送消息到之前定义的消息队列。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>struct message
{long mtype;char mtext[100];
};int main()
{// 创建唯一的键key_t key;if ((key = ftok("progfile", 66)) == -1){printf("ftok failed\n");return -1;}// 获取消息队列IDint msgid;if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1){printf("msgget failed\n");return -1;}// 设置消息类型和内容struct message msg;msg.mtype = 1;strcpy(msg.mtext, "Hello, Hope_Wisdom");// 发送消息if (msgsnd(msgid, &msg, sizeof(msg), 0) == -1){printf("msgsnd failed\n");return -1;}printf("Message Sent\n");return 0;
}

相关文章:

  • 关于TIAV20 PLCSIM仿真错误的原因
  • ST表(稀疏表)
  • Unity基础学习(十一)核心系统---光源系统基础
  • 机器人运动控制原理浅析-UC Berkeley超视觉模态模型
  • 【Python 算法零基础 2.模拟 ⑤ 基于栈和队列】
  • 【递归、搜索与回溯算法】导论
  • java加强 -List集合
  • 应急响应基础模拟靶机-security2
  • 御网杯2025 Web,Msic,密码 WP
  • 深入解析多选字段的存储与查询:从位运算到数据库设计的最佳实践
  • uni-app学习笔记(二)--vue页面代码的构成和新建页面
  • html body 设置heigth 100%,body内元素设置margin-top出滚动条(margin 重叠问题)
  • [学习]RTKLib详解:convkml.c、convrnx.c与geoid.c
  • 二、transformers基础组件之Tokenizer
  • 智能座舱开发工程师面试题
  • vue中理解MVVM
  • Ubuntu 22虚拟机【网络故障】快速解决指南
  • Qt坐标系 + 信号和槽 + connect函数(8)
  • LangChain入门(七) 提取和输出结构化数据
  • AI Agent(10):个人助手应用
  • 独行侠以1.8%概率获得状元签,NBA原来真的有剧本?
  • 成都警方通报:8岁男孩落水父母下水施救,父亲遇难
  • 退休10年后,70岁成都高新区管委会原巡视员王晋成被查
  • 第1现场 | 印巴停火次日:当地民众逐渐恢复正常生活
  • 宣布停火后,印控克什米尔地区再次传出爆炸声
  • 瑞士联邦主席凯勒-祖特尔、联邦副主席帕姆兰会见何立峰