type
status
date
slug
summary
tags
category
icon
password
Linux基于责任链模式实现消息队列
概述
消息队列提供了一个从一个进程向另外一个进程发送有类型块数据的方法
每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值
消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX)
每个消息队列的总的字节数也是有上限的(MSGMNB),系统上消息队列的总数也有上限(MSGMNI)的
消息队列的生命周期是随内核的
ipcs -q && ipcrm -q msgfd
消息队列支持全双工通信
源码
/usr/include/linux/ipc.h
,内核为每个IPC对象维护一个数据结构消息队列结构
/usr/include/linux/msg.h
接口
msgget

参数
- key : 某个消息队列的名字
- msgflg :由九个权限标志构成,它们的⽤用法和创建文件时使用的mode模式标志是一样
返回值
- 成功返回一个非负整数,即该消息队列的标识码;失败返回-1
msgctl

参数
- msgid : 由msgget 函数返回的消息队列标识码
- cmd :将要采取的动作(有三个可取值),分别如下:

- buf : 属性缓冲区
返回值
- 成功返回0;失败返回-1
msgsnd

参数
- msgid : 由msgget 函数返回的消息队列标识码
- msgp:是一个指针,指针指向准备发送的消息
- msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个
long int
长整型
- msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情, 0即可( msgflg=IPC_NOWAIT 表⽰示队列满不等待,返回EAGAIN 错误 )。
返回值
- 成功返回0;失败返回-1
消息主体
msgrcv

参数
- msgid : 由
msgget
函数返回的消息队列标识码
- msgp :是一个指针,指针指向准备接收的消息
- msgsz :是
msgp
指向的消息长度,这个长度不含保存消息类型的那个long int
长整型
- msgtype :它可以实现接收消息的类型,也可以模拟优先级的简单形式进行接收
- msgflg :控制着队列中没有相应类型的消息可供接收时将要发⽣生的事
返回值
- 成功返回实际放到接收缓冲区⾥里去的字符个数,失败返回-1
msgflg标志位
msgtype=0返回队列第一条信息msgtype>0返回队列第一条类型等于msgtype的消息msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满⾜足条件的消息类型最小的消息msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。msgflg=MSG_NOERROR,消息大小超过msgsz时被截断msgtype>0且msgflg=MSG_EXCEPT,接收6 类型不等于msgtype的第一条消息
消息队列实现
MsgQueue.hpp
Client
Server
基于责任链模式实现消息队列框架
新需求:
client
发送给server 的输入内容,拼接上时间,进程pid信息
server
收到的内容持久化保存到文件中
- 文件的内容如果过大,要进行切片保存并在指定的目录下打包保存,命令自定义
解决方案:责任链模式
一种行为设计模式,它允许你将请求沿着处理者链进行传递。每个处理者都对请求进行检查,以决定是否处理它。如果处理者能够处理该请求,它就处理它;否则,它将请求传递给链中的下一个处理者。这个模式使得多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的紧耦合。
基于责任链模式实现消息队列实现
ChainOfResponsibility.hpp
Client.cc
Server.cc
进程间通信的消息队列为什么低效
- 数据拷贝开销:当进程向消息队列发送消息时,数据需要从用户空间拷贝到内核空间;同样,接收进程从消息队列读取消息时,数据再从内核空间拷贝到用户空间。这种两次拷贝的过程增加了系统开销,降低了通信效率。
- 消息大小限制:消息队列中的每个消息体有最大长度限制,且队列包含的消息体总长度也有限制。这在大数据传输场景下不够高效。
- 同步和阻塞:消息队列的发送和接收操作通常是同步的,即发送进程可能需要等待消息被接收后才能继续执行,这会影响系统的并发性能。