进程通信之消息队列

文章目录

  • 消息队列
    • 消息队列VS管道
  • System V 消息队列
    • 系统管理命令
    • 核心函数
      • 创建/获取消息队列
      • 发送消息
      • 接收消息
      • 控制操作
    • 消息队列通信
  • POSIX 消息队列
    • 特点
    • 核心函数
      • 创建/打开队列
      • 发送消息
      • 接收消息
      • 关闭与删除
    • 文件系统集成
      • 查看消息配置
    • 异常处理
    • 消息队列通信
  • System V vs POSIX 对比

消息队列

  • 内核维护的进程间通信(IPC)机制
  • 以消息为单位进行数据交换(非字节流)
  • 支持不同类型消息的分类处理
  • 消息队列独立于创建进程存在

消息队列VS管道

特性管道消息队列
数据类型字节流结构化消息
通信方式先进先出支持消息类型过滤
持久性进程结束即消失显式删除才消失
容量固定缓冲区可配置消息数量

System V 消息队列

系统管理命令

# 查看所有IPC对象ipcs# 创建消息队列(键值12)ipcmk -Q12# 删除消息队列(ID为1)ipcrm -q1

核心函数

创建/获取消息队列

#include<sys/msg.h>intmsgget(key_tkey,intmsgflg);
  • key:消息队列键值(IPC_PRIVATE 或 ftok() 生成)
    • 可以使用ftok()函数生成,也可以指定为IPC_PRIVATE创建一个新的消息队列
  • msgflg:标志位(IPC_CREAT | 0666),
    • IPC_CREAT创建消息队列,IPC_EXCLIPC_CREAT一起使用确保创建新的消息队列
  • 返回:成功返回消息队列标识符 (msqid),失败返回 -1

发送消息

intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);
  • msqid:消息队列ID
  • msgp:消息结构体指针(必须包含long mtype)
  • msgsz:消息数据长度(不含mtype)
  • msgflg:标志位(0 或 IPC_NOWAIT)

接收消息

ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);
  • msqid: 消息队列标识符
  • msgp: 指向消息结构的指针
  • msgsz: 消息缓冲区的最大长度
  • msgtyp:消息类型选择:
    • 0:接收第一个消息
    • >0:接收指定类型的第一个消息
    • <0:接收类型≤|msgtyp|的最小类型的消息
  • msgflg: 标志位,例如IPC_NOWAIT非阻塞接收
  • 返回值: 成功返回接收到的消息数据的长度,失败返回 -1

控制操作

intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);
  • msqid: 消息队列标识符
  • cmd
    • IPC_RMID:删除队列
    • IPC_STAT:获取状态
    • IPC_SET:设置属性
  • buf: 指向msqid_ds结构的指针
  • 返回值: 成功返回 0,失败返回 -1

消息队列通信

  • 发送端
#include<sys/msg.h>#include<string.h>#include<stdio.h>structmsgbuf{longmtype;// 消息类型(必须 > 0)charmtext[100];// 消息数据};intmain(){key_tkey=ftok(".",'a');// 生成键值intmsqid=msgget(key,IPC_CREAT|0666);structmsgbufmsg;msg.mtype=1;// 设置消息类型strcpy(msg.mtext,"Hello from sender");//msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0);if(msgsnd(msqid,&msg,sizeof(msg.mtext),0)==-1){perror("msgsnd");exit(1);}printf("Message sent: %s\n",msg.mtext);return0;}
  • 接收端
#include<sys/msg.h>#include<stdio.h>structmsgbuf{longmtype;charmtext[100];};intmain(){key_tkey=ftok(".",'a');intmsqid=msgget(key,0666);structmsgbufmsg;// msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0);if(msgrcv(msqid,&msg,sizeof(msg.mtext),1,0)==-1){perror("msgrcv");exit(1);}printf("Received: %s\n",msg.mtext);msgctl(msqid,IPC_RMID,NULL);// 删除消息队列return0;}

POSIX 消息队列

特点

  • 更现代的API设计
  • 支持优先级消息
  • 与文件系统集成
  • 提供更多控制选项

核心函数

创建/打开队列

#include<mqueue.h>// 仅打开已存在的消息队列mqd_tmq_open(constchar*name,intoflag);// 打开或创建新的消息队列,带属性配置mqd_tmq_open(constchar*name,intoflag,mode_tmode,structmq_attr*attr);
  • name:队列名称(以/开头,如/myqueue, 且后续不能再包含其他<font style="color:rgb(31, 35, 41);background-color:rgba(0, 0, 0, 0);">/</font>),系统级可见的,不同进程通过相同 name 访问同一个消息队列
  • oflag:O_CREAT | O_RDONLY | O_WRONLY | O_RDWR
  • mode:仅当 oflag 包含 O_CREAT 时有效,用于指定新消息队列的访问权限,取值与 open() 函数的权限一致(例如 0644:所有者读写、同组读、其他读),最终权限会被进程的 umask 掩码修正(实际权限 = mode & ~umask)
  • attr:仅当 oflag 包含 O_CREAT 时有效,用于指定新消息队列的属性(若为 NULL,则使用系统默认属性),struct mq_attr 核心成员包括:
    • mq_maxmsg:队列最大可容纳的消息数量
    • mq_msgsize:队列中单个消息的最大字节长度
    • mq_curmsgs:队列当前的消息数量(仅用于查询,创建时设置无效)
  • 返回值:
    • 成功:返回一个有效的 消息队列描述符(mqd_t 类型),后续所有消息队列操(mq_send/mq_receive 等)均依赖该描述符
    • 失败:返回 (mqd_t)-1,同时设置全局变量 errno 指示错误原因(例如 EEXIST:O_CREAT|O_EXCL 时队列已存在;ENOENT:队列不存在且未指定 O_CREAT)

发送消息

#include<mqueue.h>intmq_send(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedintmsg_prio);
  • mqdes:由 mq_open() 成功返回的消息队列描述符,标识要操作的目标消息队列
  • msg_ptr:指向要发送的消息数据缓冲区的指针,消息数据可以是任意二进制数据(无格式要求)
  • msg_len: 指定msg_ptr指向的消息的长度,此长度必须小于或等于队列的mq_msgsize属性,允许使用零长度的消息,即0 < msg_len ≤ 消息队列的 mq_msgsize 属性
  • msg_prio:优先级(0最低,数值越大优先级越高,越先被接收),若无需优先级,可设为 0(默认优先级)
  • 返回值:
    • 成功:返回 0,表示消息已成功写入消息队列
    • 失败:返回 -1,同时设置 errno 指示错误原因(例如 EAGAIN:非阻塞模式下队列已满;EBADF:无效的消息队列描述符或无写权限)

接收消息

  • mq_receive()从消息队列描述符 mqdes 引用的消息队列中删除优先级最高的最早消息,并将其放置在msg_ptr指向的缓冲区中
  • 如果队列为空,则默认情况下,mq_receive()会阻塞,直到消息可用,或者调用被信号处理程序中断
  • 接收最高优先级的最早消息
ssize_tmq_receive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsignedint*msg_prio);
  • mqdes:由 mq_open() 成功返回的消息队列描述符,标识要操作的目标消息队列
  • msg_ptr:指向用于接收消息数据的缓冲区的指针,需提前分配足够大小的内存空间
  • msg_len: 指定 msg_ptr 指向的缓冲区的大小,必须大于或等于消息队列的 mq_msgsize 属性
  • msg_prio:指向用于存储接收消息优先级的变量指针,接收成功后,消息的优先级会被写入该变量,若不关心消息优先级,可传入 NULL
  • 返回值:
    • 成功:返回实际接收到的消息数据的字节长度(ssize_t 类型,非负整数)
    • 失败:返回 -1,同时设置 errno 指示错误原因(例如 EAGAIN:非阻塞模式下队列为空;EMSGSIZE:接收缓冲区大小 msg_len < mq_msgsize)

关闭与删除

intmq_close(mqd_tmqdes);// 关闭队列描述符intmq_unlink(constchar*name);// 删除队列文件
  • mqdes: 由 mq_open() 成功返回的消息队列描述符,标识要关闭的消息队列
  • name:与 mq_open() 中一致的消息队列唯一标识名(必须以 / 开头,格式合法),标识要删除的目标消息队列
  • 返回值:
    • 成功:返回 0,表示消息队列描述符已成功关闭/消息队列的链接已被移除
    • 失败:返回 -1,同时设置 errno 指示错误原因

文件系统集成

  • 在 Linux 上,消息队列是在虚拟文件系统中创建的
  • 挂载文件系统后,可以使用通常用于文件的命令(例如,ls 和 rm )来查看和作系统上的消息队列
# 挂载消息队列文件系统mkdir/dev/mqueuemount-t mqueue none /dev/mqueue# 查看队列信息ls/dev/mqueue/cat/dev/mqueue/myqueue# 目录中每个文件的内容都由一行组成,其中包含有关队列的信息:# 输出:QSIZE:129 NOTIFY:2 SIGNO:0 NOTIFY_PID:8260
  • QSIZE: 队列中所有消息的数据字节数
  • NOTIFY_PID: 如果该值为非零,则具有此 PID 的进程已使用**mq_notify()**来注册异步消息通知,其余字段描述通知的发生方式
  • NOTIFY: 通知方式:
    • 0SIGEV_SIGNAL
    • 1表示SIGEV_NONE
    • 2SIGEV_THREAD
  • SIGNO: 用于SIGEV_SIGNALSIGNO信号

查看消息配置

# 默认消息大小 cat/proc/sys/fs/mqueue/msgsize_default # 默认8192字节 # 最大消息大小 cat/proc/sys/fs/mqueue/msgsize_max # 限制值

异常处理

// 检查消息队列是否已满if(msgsnd(msqid,&msg,size,IPC_NOWAIT)==-1){if(errno==EAGAIN){// 队列已满处理逻辑}}// POSIX 非阻塞接收if(mq_receive(mqdes,buf,size,&prio)==-1){if(errno==EAGAIN){// 队列为空}}

消息队列通信

  • 发送端
#include<mqueue.h>#include<string.h>#include<fcntl.h>#defineQUEUE_NAME"/my_queue"#defineMSG_PRIORITY1intmain(){mqd_tmqdes=mq_open(QUEUE_NAME,O_WRONLY|O_CREAT,0666,NULL);charmessage[]="Hello, POSIX!";mq_send(mqdes,message,strlen(message),MSG_PRIORITY);mq_close(mqdes);return0;}
  • 接收端
#include<mqueue.h>#include<stdio.h>#defineQUEUE_NAME"/my_queue"#defineMAX_MSG_SIZE8192intmain(){mqd_tmqdes=mq_open(QUEUE_NAME,O_RDONLY);charbuffer[MAX_MSG_SIZE];unsignedintpriority;ssize_tlen=mq_receive(mqdes,buffer,MAX_MSG_SIZE,&priority);buffer[len]='\0';printf("[优先级:%u] %s\n",priority,buffer);mq_close(mqdes);// mq_unlink(QUEUE_NAME); // 删除队列return0;}

System V vs POSIX 对比

特性System VPOSIX
API风格较旧较新,类似文件操作
命名方式数字键值路径名
消息优先级
阻塞控制有限更灵活
文件系统集成有(/dev/mqueue)
可移植性广泛较新系统
默认限制系统配置可调节

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1141697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通信协议仿真:通信协议基础_(9).通信协议仿真案例分析

通信协议仿真案例分析 在上一节中&#xff0c;我们介绍了通信协议的基础知识&#xff0c;包括通信协议的定义、分类以及重要性。本节将通过具体的案例分析&#xff0c;深入探讨通信协议仿真的实际应用和实现方法。我们将从简单的串行通信协议开始&#xff0c;逐步分析更复杂的网…

hal_uart_transmit驱动开发全流程:初始化到发送一文说清

从零搞懂HAL_UART_Transmit&#xff1a;不只是调用一个函数&#xff0c;而是掌握嵌入式通信的底层逻辑你有没有遇到过这种情况&#xff1a;明明代码写得和例程一模一样&#xff0c;串口就是发不出数据&#xff1f;或者用了HAL_UART_Transmit发送日志&#xff0c;结果主循环卡住…

物理公式学习神器:免费无广含多分支助记忆

软件介绍 今天要介绍的这款工具是“物理公式手册”&#xff0c;它是应小伙伴需求专门带来的物理学习辅助软件——上次推荐数学公式手册后&#xff0c;不少人留言说想要物理版的&#xff0c;这不&#xff0c;今天就安排上这款好用的物理公式手册&#xff0c;帮大家搞定物理公式…

QoS质量配置

他们祝你挺拔&#xff0c;再挺拔一点&#xff1b;我只祝你&#xff0c;永远年少&#xff0c;永远一骑当先.1. QoS的概念 QoS(服务质量)是指一个网络能够利用各种各样的基础技术向选定的网络通信提供更好 的服务的能力。这些基础技术包括&#xff1a;帧中继&#xff08;FrameRel…

Spark大数据ETL实战:数据清洗与转换最佳实践

Spark大数据ETL实战&#xff1a;数据清洗与转换最佳实践 关键词&#xff1a;Spark、ETL、数据清洗、数据转换、大数据处理、最佳实践、分布式计算 摘要&#xff1a;本文系统解析Apache Spark在大数据ETL中的核心应用&#xff0c;聚焦数据清洗与转换的关键技术。通过深入剖析Spa…

【教程4>第10章>第20节】基于FPGA的图像sobel锐化算法开发——图像sobel锐化仿真测试以及MATLAB辅助验证

目录 1.软件版本 2.通过FPGA实现图像sobel锐化 3.testbench编写 4.程序操作视频 欢迎订阅FPGA/MATLAB/Simulink系列教程 《★教程1:matlab入门100例》 《★教程2:fpga入门100例》 《★教程3:simulink入门60例》 《★教程4:FPGA/MATLAB/Simulink联合开发入门与进阶X例》

【毕业设计】SpringBoot+Vue+MySQL 高校学科竞赛平台平台源码+数据库+论文+部署文档

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价。我就是个在校研究生&#xff0c;兼职赚点饭钱贴补生活费&…

STM32CubeMX安装步骤系统学习:配套工具链配置

STM32CubeMX安装与工具链配置全解析&#xff1a;从零搭建高效嵌入式开发环境 你是不是也曾遇到这样的情况&#xff1f;刚下载好STM32CubeMX&#xff0c;双击启动却弹出“ No Java virtual machine was found ”&#xff1b;或者好不容易打开界面&#xff0c;想生成Keil工程时…

python的sql解析库-sqlparse

内容目录 一、基本方法: 1.parse(sql)2.format(sql)3.split()4.parsestream() 二、Token三、其他类型四、案例: 提取所有查询的字段和表名 sqlparse 是一个 Python 库&#xff0c;是一个用于 Python 的非验证 SQL 解析器, 用于解析 SQL 语句并提供一个简单的 API 来访问解析后…

数字频率计共阴极数码管驱动电路实战

数码管驱动实战&#xff1a;如何用51单片机点亮4位频率计显示屏&#xff1f;你有没有遇到过这样的问题&#xff1a;想做个数字频率计&#xff0c;测出的频率值却没法“亮”出来&#xff1f;或者好不容易接上数码管&#xff0c;结果显示闪烁、重影&#xff0c;甚至MCU IO口直接拉…

Java Web 教学资源库系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

&#x1f4a1;实话实说&#xff1a;有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着信息技术的快速发展&#xff0c;教育领域对数字化教学资源的需求日益增长。传统的教学资源管理方式存在资源分散、检索效率低、共享困难等问题…

Python爬虫完整代码拿走不谢

对于新手做Python爬虫来说是有点难处的&#xff0c;前期练习的时候可以直接套用模板&#xff0c;这样省时省力还很方便。 使用Python爬取某网站的相关数据&#xff0c;并保存到同目录下Excel。 直接上代码&#xff1a; import re import urllib.error import urllib.requestimp…

系统管理工具,多功能隐私清理文件粉碎工具

软件介绍 今天给大伙儿安利个全能的系统管理工具&#xff0c;它叫 Windows超级管理器。功能那叫一个全乎&#xff0c;系统检测、文件清理、隐私保护、磁盘管理、文件粉碎这些实用活儿它都能干&#xff0c;堪称系统管家&#xff01; 绿色单文件版&#xff1a;小巧便携的系统管…

SpringBoot+Vue 智能推荐卫生健康系统平台完整项目源码+SQL脚本+接口文档【Java Web毕设】

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价。我就是个在校研究生&#xff0c;兼职赚点饭钱贴补生活费&…

【踩坑记】WSL1 下 Docker 报错 iptables: No chain/target/match by that name 排查实录

这是一篇为你整理的“踩坑记”&#xff0c;还原了从报错、排查到发现核心原因并解决的全过程。【踩坑记】WSL1 下 Docker 报错 iptables: No chain/target/match by that name 排查实录1. 背景与环境今天在 WSL (Ubuntu 24.04) 环境下部署 Dify 项目&#xff0c;执行启动命令时…

autosar软件开发中诊断协议栈配置实践案例

AUTOSAR诊断协议栈配置实战&#xff1a;从UDS服务到DTC管理的全链路解析在一辆现代智能汽车中&#xff0c;当你用诊断仪读取一个故障码、刷新ECU程序&#xff0c;或是远程获取车辆实时数据时——背后支撑这一切的&#xff0c;正是AUTOSAR架构中的诊断通信协议栈。它不仅是连接整…

MPC5634 Bootloader

MPC5634 Bootloader嵌入式工程师最怕遇到设备变砖&#xff0c;而好的Bootloader设计就是咱们的救命稻草。今天咱们来盘一盘飞思卡尔MPC5634这颗工业级控制器的Bootloader实现&#xff0c;直接上干货不啰嗦。先说启动流程&#xff0c;这货上电先执行0x00地址的启动代码。来看关键…

无线网络仿真:5G网络仿真_(3).5G关键技术和性能指标

5G关键技术和性能指标 1. 大规模MIMO技术 1.1 原理 大规模MIMO&#xff08;Multiple-Input Multiple-Output&#xff09;技术是5G网络中的一项重要技术&#xff0c;通过在基站和用户设备上部署大量的天线&#xff0c;可以显著提升无线通信系统的容量和频谱效率。大规模MIMO技术…

洗衣店订单管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

&#x1f4a1;实话实说&#xff1a;有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着现代生活节奏的加快&#xff0c;洗衣服务行业逐渐成为城市居民日常生活的重要组成部分。传统的洗衣店管理方式依赖手工记录订单信息&#xff0…

RabbitMQ 集群部署方案

RabbitMQ 一、安装 RabbitMQ 二、更改配置文件 三、配置集群 四、测试 环境准备&#xff1a;三台服务器&#xff0c;系统是 CentOS7 IP地址分别是&#xff1a; rabbitmq1&#xff1a;192.168.152.71rabbitmq2&#xff1a;192.168.152.72rabbitmq3&#xff1a;192.168.152.…