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

进程间通信(消息队列)

消息队列概念
Linux系统中消息队列(Message Queue)是进程间通信的一种方式,这种通信机制的好处是可以传输指定类型(用户可以自行定义)的数据,相同类型的数据根据到达顺序在队列中进行排队。
当然,不同类型的数据不能处于同一个队列中,也就是说系统中可能存在多个消息队列,每个消息队列中的数据类型都是不同的,所以用户打算读取消息队列中的数据时也需要指定数据类型,才可以从存储该类型数据的消息队列中读取有效数据。
Linux系统每个创建的消息队列都具有一个唯一的键值key,进程可以通过指定消息队列的键值来向消息队列发送数据。Linux系统中提供了一个shell命令:ipcs -a来查看系统中所有的IPC对象的信息。
image
image

创建消息队列
Linux系统提供了一个名称叫做msgget()的函数接口,用户利用该接口可以创建或者打开一个消息队列,同样Linux系统中提供了一个shell命令:ipcmk 可以用于创建IPC对象。
(1)ipcmk命令
image
image
image
(2)msgget()函数
image
msgget函数有两个参数,第一个参数需要传入一个key_t类型的值,该值指的是要创建的消息队列的key键值,key也可以称为密钥。 键值类型key_t其实在内核源码中指的是int类型,如下图:
image
msgget()函数的第二个参数指的是创建消息队列的标志,其中IPC_CREAT指的是如果消息队列不存在则创建,IPC_EXCL指的是如果消息队列存在则表示函数调用失败。
另外,也可以指定消息队列的权限,权限的结构和open函数的mode类型,采用八进制表示,只不过消息队列不需要设置执行权限,所以权限设置为0644即可。
msgget()函数调用成功,则返回消息队列的标识符,如果调用失败,则返回-1并设置错误码。
可以看到调用msgget()函数需要传入一个键值key,这个键值key是否可以由用户指定?
回答:可以由用户指定,但是不建议这样操作,因为可能有多个进程都会创建消息队列,如果某两个进程指定的键值key相同,则会创建失败,所以应该由系统生成唯一的键值key。
Linux系统中提供了一个名称叫做ftok()的函数接口,利用该接口可以生成IPC对象的键值key,该接口的使用规则如下:
image
可以看到,ftok()函数可以把一个指定路径的文件和一个指定的项目id转换为一个system-V IPC对象使用的键值key。
(1)函数参数
ftok()函数的第一个参数指的是系统中已经存在并且可以访问的一个文件的路径,用户可以指定一个文件,但是该文件必须存在且可以被访问,其实就是为了得到文件的属性信息中的inode编号和设备编号,因为Linux系统中一个文件的inode编号是唯一的。
ftok()函数的第二个参数指的是项目ID,这个可以由用户进行指定,虽然参数proj_id的类型是整型int,但是只会用到最低8it,所以这个参数的范围其实是1~255,因为这个参数的值必须是非0值。
(2)返回结果
ftok()函数的返回值:当函数调用成功后,则返回生成的键值key,如果调用失败,则返回-1。
(3)注意事项
在man手册中提到ftok()函数生成的键值key的组成:proj_id的低8位+ 设备编号的低8位+ inode编号的低16位。

访问消息队列

思考:用户如果创建了一个消息队列,那进程如何向消息队列收发数据,数据类型如何指定?
回答:Linux系统中提供了一个名称叫做msgsnd()的函数接口,用户利用该函数可以向指定的消息队列发送消息,同时提供了一个名称叫做msgrcv()的函数接口,用户利用该接口可以从指定的消息队列中读取消息。
image

(1)发送消息
image
image
msgsnd函数的第一个参数msgid指的是消息队列的标识符,该标识符可以通过msgget函数得到。
msgsnd函数的第二个参数msgp指的是一个指向struct msgbuf类型的结构体指针,该结构体中有两个成员,其中一个成员mtype指的是消息类型,必须是一个大于0的正整数,另一个成员mtext指的是消息正文,类型可以是数组或者其他结构。
msgsnd函数的第三个参数msgsz指的是消息正文的大小,按字节计算,当然msgsz的值必须是非负整数,可以设置为0,表示消息正文的长度为0。
msgsnd函数的第四个参数msgflg指的是消息队列的标志,如果该标志设置为IPC_NOWAIT,则表示不阻塞,此时如果待写入的消息的长度大于消息队列剩余空间,则直接返回并报错。
image

(2)读取消息
image
第一个参数:msgqid指的是MSG对象的标识符ID,MSG标识符可以通过msgget()函数获取。

第二个参数:msgp指的是存放消息的缓存地址,该地址下存储的是struct msgbuf结构体。

第三个参数:msgsz指的是存放消息的缓存的大小,按照字节计算,如果消息正文的大小大于用户设置的缓存大小,则根据msgflg是否为MSG_NOERROR进行判断,如果msgflg设置为MSG_NOERROR ,则可以读取对应字节的消息,如果msgflg没有设置,则无法读取消息并报错。

第四个参数:msgtyp指的是要接收消息的类型,在调用msgsnd函数时构造的消息结构体中有该成员的值。

1)等于0:指的是不区分类型,直接读取MSG中的第一个消息。

2)大于0:读取类型为指定msgtyp的第一个消息(若msgflg被配置了MSG_EXCEPT则读取除了类型为msgtyp的第一个消息)。

3)小于0:读取类型小于等于msgtyp绝对值的第一个具有最小类型的消息。例如当MSG对象中有类型为3、1、5类型消息若干条,当msgtyp为-3时,类型为3的第一个消息将被读取。

第五个参数:msgflg指的是接收消息选项,如果msgflg设置为0,指的是默认接收模式,在MSG中无指定类型消息时阻塞。

1)IPC_NOWAIT :指的是非阻塞接收模式,当MSG中没有指定类型消息时直接退出函数
2)MSG_EXCEPT :指的是读取除msgtyp之外的第一个消息。
3)MSG_NOERROR:如果待读取的消息尺寸比msgsz大只返回msgsz部分,其余部分丢弃

http://www.wxhsa.cn/company.asp?id=4524

相关文章:

  • 有点长所以单发的闲话(对acgn的看法(存疑))
  • 【光照】Unity中的[光照模型]概念辨析
  • 深入解析:Shell脚本监控系统资源详解
  • 计算几何全家桶
  • 完整教程:从无声视频中“听见”声音:用视觉语言模型推理音频描述
  • Win10如何安装语音包
  • C#通过TCP/IP控制康奈视读码枪实现方案
  • 链表
  • 利用三方APP[IP切换助手]使用socks5
  • 智能卫浴雷达模块感应方案WT4101寿命长不怕干扰
  • 修改Windows 资源器中文件的创建时间或更新时间
  • Mysql练习,15个必练语句带你玩转数据库
  • 威力导演2026中文版 CyberLink PowerDirector 2026 v24.0 旗舰版更新内容
  • 越权漏洞
  • GAS_Aura-Ability Tasks
  • 本地大模型的崛起:为什么越来越多人不用云端 AI?
  • Gitee:国产代码托管平台如何重塑企业研发效能版图
  • CompassBench 大模型评测
  • Windows截图工具Acropalypse漏洞剖析:开发者中心安全的重要教训
  • bootstrap-flex总结
  • 【源码解读之 Mybatis】【基础篇】-- 第2篇:配置系统深度解析
  • eSIM笔记
  • 拯救者Y7000过热降频解决方法
  • 普通大语言模型(LLM)和向量化模型(Embedding Model)的区别以及其各自的作用
  • ios电脑如何改成windows系统
  • PythonFlask 运用 DBUtils 创建通用连接池
  • 帧同步、快照同步与状态同步
  • 内存一致性模型
  • MahMetro 框架学习
  • 基于MATLAB的标准化降水蒸散指数(SPEI)实现