05.消息队列

1.消息队列

消息队列的概述:

消息”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。

消息被发送到队列中。“消息队列”是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时充当中间人。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。

消息队列---缓存区,用于保存有效数据

linux操作系统中的消息队列:

消息队列是消息的链表,存放在内存中,由内核维护

消息队列的特性:

  • 消息队列中的消息是有类型的。
  • 消息队列中的消息是有格式的。
  • 消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取,编程时
  • 可以按消息的类型读取。
  • 消息队列允许一个或多个进程向它写入或者读取消息。
  • 与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除。
  • 每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的。
  • 只有内核重启或人工删除消息队列时,该消息队列才会被删除。若不人工删除消息队列,消息队列会一直存在于系统中。

为什么学习了管道之后,还要学习队列????

管道中的消息是没有固定类型的

管道相当于对消息的复制传输

管道是先进先出(FIFO)

在 ubuntu 1204版本中消息队列限制值如下:

每个消息内容最多为 8K 字节

每个消息队列容量最多为 16K 字节

系统中消息队列个数最多为 1609 个

系统中消息个数最多为 16384 个

1804版本:

每个消息内容最多为 8K 字节

每个消息队列容量最多为 16K 字节

系统中消息队列个数最多为 32000 个

系统中消息个数最多为 16384 个

具体的查看方式:

1.查看消息队列的设置信息 查看每个消息的最大长度: cat /proc/sys/kernel/msgmax 查看每个消息队列总的字节数: cat /proc/sys/kernel/msgmnb 查看消息队列的总数上限: cat /proc/sys/kernel/msgmni 2.调整消息队列的设置信息 通过root用户修改/etc/sysctl.conf中的配置可调整上述参数的大小(如果本身/etc/sysctl.conf中没有相应的配置信息,则可以新增): kernel.msgmni=65536 kernel.msgmax=81920 kernel.msgmnb=4194304 修改后执行下面的命令生效: /sbin/sysctl -p 3.查看消息队列: ipcs -q :查看消息队列 ipcs -pq :查看消息队列对应的用户、发送和接收进程pid ipcs -q -i msgid :查看该msgid的消息队列的详细情况 ipcrm -Q key:删除消息队列

查看当前系统中的消息队列

消息队列创建和使用:

key 值可以是人为指定的(自定义), 也可以通过 ftok 函数获得

获取键值:

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:
获得项目相关的唯一的 IPC 键值。ftok内部集成了一个算法,用于获取一个唯一返回值,作为队列使用的键值
参数:
pathname: 路径名(可以随意设置,但是必须真实有效,而且是绝对路径)
proj_id: 项目 ID, 非 0 整数(只有低 8 位有效--255)--(随便设置)
返回值:
成功返回 key 值, 失败返回 -1。

创建队列:

#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:
创建一个新的或打开一个已经存在的消息队列。 不同的进程调用此函数,
只要用相同的 key 值就能得到同一个消息队列的标识符。
参数:
key: IPC 键值。
msgflg: 标识函数的行为及消息队列的权限。
参数:
msgflg 的取值:
IPC_CREAT: 创建消息队列。
IPC_EXCL: 检测消息队列是否存在。
位或权限位: 消息队列位或权限位后可以设置消息队列的访问权限, 格式和 
open 函数的mode_t 一样, 但可执行权限未使用。
返回值:
成功: 消息队列的标识符, 失败: 返回-1。

相关的操作指令:

使用命令操作消息队列: 查看消息队列 ipcs -q 删除消息队列 ipcrm -q msqid(消息队列的id) 消息队列的消息的格式。

消息的具体格式(必须):

typedef struct _msg
{
long mtype; /*消息类型--MQTT*/
char name[20];
char mtext[100]; /*消息正文*/
float high;
... /*消息的正文可以有多个成员*/}MSG;

消息类型必须是长整型的, 而且必须是结构体类 型的第一个成员, 类型下面是消息正文, 正文可以 有多个成员(正文成员可以是任意数据类型的) 。

发送消息:

#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg);
功能:
将新消息添加到消息队列。
参数:
msqid: 消息队列的标识符。
msgp: 待发送消息结构体的地址。
msgsz: 消息正文的字节数sizeof(msg)-sizeof(long)。
msgflg: 函数的控制属性
0: msgsnd 调用阻塞直到条件满足为止。
IPC_NOWAIT: 若消息没有立即发送则调用该函数的进程会立即返回。
返回值:
成功: 0; 失败: 返回-1。

接收消息:

#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:
从标识符为 msqid 的消息队列中接收一个消息。 一旦接收消息成功, 则消息
在消息队列中被删除。
参数:
msqid: 消息队列的标识符, 代表要从哪个消息列中获取消息。
msgp: 存放消息结构体的地址。
msgsz: 消息正文的字节数sizeof(msg)-sizeof(long)。
msgtyp: 消息的类型、 可以有以下几种类型
msgtyp = 0: 返回队列中的第一个消息
msgtyp > 0: 返回队列中消息类型为 msgtyp 的消息
msgtyp < 0: 返回队列中消息类型值小于或等于 msgtyp 绝对值的消息, 如果这
种消息有若干个, 则取类型值 最小的消息。注意:若消息队列中有多种类型的消息, msgrcv 获取消息的时候按消息类型获取, 
不是先进先出的。
在获取某类型消息的时候, 若队列中有多条此类型的消息, 则获取最先添加的消
息, 即先进先出原则。
msgflg: 函数的控制属性
0: msgrcv 调用阻塞直到接收消息成功为止。
MSG_NOERROR:若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节,
且不通知消息发送进程。
IPC_NOWAIT:调用进程会立即返回。 若没有收到消息则立即返回-1。
返回值:
成功返回读取消息的长度, 失败返回-1

消息队列的控制:

#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
对消息队列进行各种控制, 如修改消息队列的属性, 或删除消息消息队列。
参数:
msqid: 消息队列的标识符。
cmd: 函数功能的控制。
buf: msqid_ds 数据类型的地址, 用来存放或更改消息队列的属性。
cmd: 函数功能的控制
IPC_RMID: 删除由 msqid 指示的消息队列, 将它从系统中删除并破坏相关
数据结构。
IPC_STAT: 将 msqid 相关的数据结构中各个元素的当前值存入到由 buf
指向的结构中。
IPC_SET: 将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中
的对应值。
返回值: 成功: 返回 0; 失败: 返回 -1

struct msqid_ds结构体内容:

struct msqid_ds {struct ipc_perm msg_perm;     /* Ownership and permissions */time_t          msg_stime;    /* Time of last msgsnd(2) */time_t          msg_rtime;    /* Time of last msgrcv(2) */time_t          msg_ctime;    /* Time of last change */unsigned long   __msg_cbytes; /* Current number of bytes inqueue (nonstandard) */msgqnum_t       msg_qnum;     /* Current number of messagesin queue */msglen_t        msg_qbytes;   /* Maximum number of bytesallowed in queue */pid_t           msg_lspid;    /* PID of last msgsnd(2) */pid_t           msg_lrpid;    /* PID of last msgrcv(2) */};

struct ipc_perm结构体:

struct ipc_perm {key_t          __key;       /* Key supplied to msgget(2) */uid_t          uid;         /* Effective UID of owner */gid_t          gid;         /* Effective GID of owner */uid_t          cuid;        /* Effective UID of creator */gid_t          cgid;        /* Effective GID of creator */unsigned short mode;        /* Permissions */unsigned short __seq;       /* Sequence number */};

消息队列的使用步骤:

1.获取一个唯一键值--ftok()

2.根据键值创建消息队列--msgget()

3.整理数据格式--typedef struct _msg

4.发送数据--msgsnd();

5.接收数据--msgrcv();

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
//进程间的通信--队列中使用的头文件
#include <sys/ipc.h>
#include <sys/msg.h>typedef struct _msg
{
long mtype; /*消息类型--类似MQTT*/
char name[20];
char mtext[64]; /*消息正文*/}MSG;int main(void)
{MSG msg_rev;struct msqid_ds buf;//获取键值key_t  key= ftok("./",128);printf("key-->%d\n",key);//创建队列//int msgget(key_t key, int msgflg);int msg_id= msgget(3,IPC_CREAT|0666);printf("msg_id-->%d\n",msg_id);//tom---mtype--->0x03// msg.mtype=3;//消息类型// strcpy(msg.name,"tom");// strcpy(msg.mtext,"how are you?");//发送数据//int msgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg);// msgsnd(msg_id,&msg,sizeof(msg)-sizeof(long),0);//阻塞//接收数据//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);int ret= msgrcv(msg_id,&msg_rev,sizeof(msg_rev)-sizeof(long),3,0);printf("接收到的消息长度:%d\n",ret);printf("%s :%s \n",msg_rev.name,msg_rev.mtext);//所有的需要进行的操作结束之后// msgctl(msg_id,IPC_RMID,&buf);return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
//进程间的通信--队列中使用的头文件
#include <sys/ipc.h>
#include <sys/msg.h>typedef struct _msg
{
long mtype; /*消息类型--类似MQTT*/
char name[20];
char mtext[64]; /*消息正文*/}MSG;int main(void)
{MSG msg;//获取键值key_t  key= ftok("./",128);printf("key-->%d\n",key);//创建队列//int msgget(key_t key, int msgflg);int msg_id= msgget(3,IPC_CREAT|0666);printf("msg_id-->%d\n",msg_id);//tom---mtype--->0x03msg.mtype=3;//消息类型strcpy(msg.name,"tom");strcpy(msg.mtext,"how are you?");//发送数据//int msgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg);msgsnd(msg_id,&msg,sizeof(msg)-sizeof(long),0);//阻塞return 0;
}

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

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

相关文章

JavaScript 之 获取当前日期的周日期范围、月日期范围

前言 实际开发中&#xff0c;有的时候产品要求需要用到日期筛选&#xff0c;日期筛选又需要用的当前日期的周日期范围&#xff0c;也有可能上一周&#xff0c;下一周这样的&#xff0c;相对应的也就又可能是当前日期的月日期范围&#xff0c;上一个月、下一个月的这样的&#x…

完全二叉树的节点个数

题目链接 完全二叉树的节点个数 题目描述 注意点 题目数据保证输入的树是完全二叉树 解答思路 最初想到的是递归计算子树对应的节点数量&#xff0c;相加就是整个二叉树的节点个数&#xff0c;但是该方法没有用到完全二叉树的特点&#xff0c;考虑是否有更加巧妙地方法根据…

五步炼丹!qwen通义千问1.5版本微调实战来了!

炼丹第一步&#xff08;数据准备&#xff09; 数据样例 我们需要至少两个json文件放在data目录&#xff0c;一个命名为dataset_info.json&#xff08;注意&#xff1a;这个文件是固定的名称&#xff0c;不要更改&#xff09;&#xff0c;还有一个是微调训练数据json文件名可以…

Day40-45 网络高级(modbus)

文章目录 Modbus起源1.起源&#xff1a;2.分类&#xff1a;3.优势&#xff1a;4.应用场景&#xff1a;5.ModbusTCP特点&#xff1a; Modbus TCP协议格式1.报文头2.寄存器3.功能码 工具软件使用.Modbus Slave&Poll2.网络调试助手.Wireshark的使用 Modbus RTU1、与Modbus TCP…

AIGC笔记--关节点6D位姿按比例融合

1--核心代码 6D位姿一般指平移向量和旋转向量&#xff0c;Maya软件中关节点的6D位姿指的是相对平移向量和欧拉旋转向量&#xff1b; 为了按比例融合两个Pose&#xff0c;首先需要将欧拉旋转向量转换为旋转矩阵&#xff0c;在将旋转矩阵转换为四元数&#xff0c;利用球面线性插值…

【JS逆向学习】猿人学第六题 js混淆 回溯

逆向目标 网址&#xff1a;https://match.yuanrenxue.cn/match/6接口&#xff1a;https://match.yuanrenxue.cn/api/match/6参数&#xff1a;payload(m、q) 逆向过程 老规矩&#xff0c;先来分析网络请求&#xff0c;加密的地方一目了然&#xff0c;没什么可多说的&#xff…

解决ubuntu 22.04新内核6.5.0-15无法编译NVIDIA显卡驱动

这里的新内核应该包括6.5.*系列的 文章目录 遇到的问题&#xff1a; 遇到的问题&#xff1a; 今天我在安装NVIDIA显卡驱动发现了一个问题&#xff0c;主要日志如下所示&#xff1a; make[3]: *** [scripts/Makefile.build:251: /tmp/selfgz1310041/NVIDIA-Linux-x86_64-550.5…

明牌了,这批组态界面算不算颜值担当?

一般来说工业组态图都不会过于追求颜值&#xff0c;好用、易用即可&#xff0c;但是在这个基础上再有颜值&#xff0c;试问谁又会拒绝呢&#xff1f; 哪一个单身狗&#xff0c;不喜欢能力强&#xff0c;有颜值的美女搭档呢&#xff0c;对不。

QT 如何在QPushButton上播放gif(终极版)

在平时浏览网站&#xff0c;或者使用软件的时候&#xff0c;经常可以见到&#xff1a;在点击了某个按钮之后&#xff0c;按钮上会显示动图以及提示文字。在QT中&#xff0c;比较常见且简单的做法就是&#xff1a;给按钮设置一个layout&#xff0c;然后在这个layout里面添加QLab…

瑞芯微ITX-3588J开发板烧录ubuntu桌面系统(图文详解)

首先进入FIrefly官网&#xff0c;这里不仅可以获得它的开发板信息教程&#xff0c;还可以获取到它的升级固件以及工具。 1、首先打开DriverInstall.exe&#xff0c;点击【驱动安装】。 2、点击【安装】&#xff0c;就会进行安装。 3、安装完成后就可以用Type-C数据线连接开发板…

Git的介绍

导出项目依赖 # 以后项目给别人需要导出项目依赖&#xff0c;放在项目路径下&#xff0c;以后在运行项目前&#xff0c;先安装依赖 一般约定俗成都叫 requirements.txt,但是会有别的&#xff1a;req.txt | dev.txt # 两种方式&#xff1a; 1、虚拟环境所有装的第三方&…

YoloV8改进策略:下采样改进|HWD改进下采样

摘要 本文使用HWD改进下采样&#xff0c;在YoloV8的测试中实现涨点。 论文解读 在卷积神经网络&#xff08;CNNs&#xff09;中&#xff0c;极大池化或跨行卷积等下采样操作被广泛用于聚合局部特征、扩大感受野和最小化计算开销。然而&#xff0c;对于语义分割任务&#xff…