消息队列

消息队列是和管道并列的概念,也是进程间通信IPC中的一种。

本文参考:消息队列(定义、结构、如何创建、消息队列的发送与接收、发送与接收实例)_咋么又饿了的博客-CSDN博客

基本概念

  • 消息队列是一种先进先出的队列型数据结构实际上是系统内核中的一个内部链表。消息被顺序插入队列中,其中发送进程将消息添加到队列末尾,接受进程从队列头读取消息
  • 多个进程可同时向一个消息队列发送消息,也可以同时从一个消息队列中接收消息消息一旦被读出就从队列中删除
  • 一个消息队列由一个标识符(即队列ID)来标识

特点

  1. 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级
  2. 消息队列独立于发送和接收进程。进程终止时,消息队列及其内容并不会被删除
  3. 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取

消息队列的结构 

如上面所说,消息队列的本质是一个链表,所以结构和之前讲的链表非常相似:

struct msgbuf
{
	long 	mtype;
	XXX     XXX; //任意的数据类型,包括结构体
}
  • mtype:指定了消息类型,为正整数,引入消息类型之后,消息队列在逻辑上由一个消息链表转化为多个消息链表。发送进程仍然无条件把消息写入队列的尾部,但接收进程却可以有选择地读取某个特定类型的消息中最接近队列头的一个,即使该消息不在队列头。相应消息一旦被读取,就从队列中删除,其它消息维持不变
  • XXX: 指定了消息的数据,可以是任意的数据类型,包括结构体

相关的API 

消息队列的创建/访问 msgget()

函数创建一个新的消息队列或访问一个已经存在的消息队列 

需要添加的库

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

函数原型

int msgget(key_t key, int msgflg);

参数列表

  • key:消息队列的关键字

当参数key取值IPC_PRIVATE时,函数创建关键字为0的消息队列在UNIX内核中虽然要求消息队列关键字唯一,但也可以创建多个关键字为0的消息队列

  • msgflg:低9位指定队列的属主、属组和其他用户的访问权限,其它位指定消息队列的创建方式

创建方式参数:

  • IPC_CREAT:创建,如存在则打开;
  • IPC_EXCL:与IPC_CREAT使用,单独使用无意义。创建时,如存在则失败
  • 返回值:成功返回队列ID,失败返回-1

使用举例

假设创建关键字为0x4321,访问权限为0666的消息队列,如队列已存在则报错。

int msgid;
msgid = msgget(0x4321, 0666|IPC_CREAT|IPC_EXCL);

消息队列的发送msgsnd()

需要添加的库

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

函数原型

int msgsnd(int msqid, void *msgp, int msgsz, int msgflg);

参数列表

  • msqid:要发送消息队列的标识号
  • msgp:指向存储待发送消息内容的内存地址,用户可设计自己的消息结构
  • msgsz:指定长度,仅记载数据的长度,不包括消息类型部分,且必须大于0
  • msgflg:控制消息发送的方式,有阻塞和非阻塞(IPC_NOWAIT)两种方式
  • 返回值:成功返回0,失败返回-1

导致msgsnd函数阻塞的原因:

  • 消息队列满
msg_cbytes(消息队列中已使用字节数) + msgsz > msg_qbytes(消息队列中可以容纳的最大字节数)
  • 消息总数满:系统中所有消息队列记载的消息总数已达到系统上限值

消息队列的接收msgrcv()

需要添加的库

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

函数原型

int msgrcv(int msgid, void *msgp, int msgsz, long msgtyp, int msgflg);

参数列表

  • msgid:消息队列标识号
  • msgp:指向接收消息的内存缓冲区
  • msgsz:指定该缓冲区的最大容量,不包括消息类型占用的部分
  • msgtyp:指定读取消息的类型
  • 0:读取消息队列中第一个消息
  • 正整数:读取消息队列中第一个类型为msgtyp的消息
  • 负整数:读取消息队列中第一个类型小于或等于msgtyp的绝对值的消息
  •  msgflg:指定了消息的接收方式
  • IPC_NOWAIT:非阻塞方式读取信息
  • MSG_NOERROR:截断读取消息
  • 返回值:成功返回消息数据的长度,失败返回-1

消息队列的控制msgctl()

需要添加的库

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

函数原型

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数列表

  • msqid:由msgget()返回的队列标识符
  • cmd:命令,可以取以下三个值
  • IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
  • IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
  • IPC_RMID:删除消息队列
  • buf:记录消息队列的信息(消息队列模式和访问权限)(默认为NULL)
  • 返回值:成功返回0,失败返回-1

实操演示

需求:写两个C程序,一个以阻塞的方式发送数据,另一个以阻塞方式来接收,消息队列的关键词是“4321”,消息类型是“123”:

回顾刚刚的知识点,所谓关键词就是指在创建/访问消息队列时msgget的第一个参数

msgget(0x4321, 0666|IPC_CREAT);

而所谓的消息类型就是在定义消息队列时,第一个成员“mtype”的值

buf.mtype = 123;

msgsend.c:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>

struct mymsgbuf{
		long mtype;
		char ctext[100];
};

int main()
{
	struct mymsgbuf buf;
	int msgid;

	msgid = msgget(0x4321, 0666|IPC_CREAT);
	if(msgid == -1){
		printf("msgqueue error\n");
		exit(1);
	}
	
	buf.mtype = 123;
	strcpy(buf.ctext, "msg from queue!\n");
	msgsnd(msgid,&buf,strlen(buf.ctext),0);


	return 0;
}

msgget.c: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>

struct mymsgbuf{
		long mtype;
		char ctext[100];
};

int main()
{
	struct mymsgbuf buf;
	int msgid;

	msgid = msgget(0x4321, 0666|IPC_CREAT);
	if(msgid == -1){
		printf("msgqueue error\n");
		exit(1);
	}

	msgrcv(msgid,&buf,sizeof(buf.ctext),123,0);
	printf("read from queue:%s\n",buf.ctext);


	return 0;
}

运行效果

先编译并运行接收的程序“msgget.c”:

可见程序正在阻塞,等待接收中...

此时再编译并运行发送的程序“msgsend.c”:

 然后此时再观察接收的程序:

数据读取成功! 

另外,在上述的例子中,只是粗略的进行了演示,严谨的代码还应该包含对于消息队列读写的成功与否的判断,同时,此处的关键词是随便设置了一个,但在实际应用中,可能出现很多消息队列,一种比较专业的定义关键词的方法是使用“ftok”函数,将一个已存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键值(也称IPC key键值):

key_t key;
key = ftok(".",1); //"." 代表当前路径

如此一来就可以得到一个,有意义且独特的KEY值

详见:

linux进程间通信--消息队列相关函数(ftok)详解_andylauren的博客-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Stable Diffusion核心算法DDPM解析

DDPM&#xff1a;Denoising Diffusion Probabilistic Model&#xff0c;去噪扩散概率模型 本文参考&#xff1a;一个视频看懂扩散模型DDPM原理推导|AI绘画底层模型_哔哩哔哩_bilibili 1、大概原理 从右往左为正向加噪过程&#xff0c;从左往右为逆向降噪过程。 在正向过程中不…

专访 BlockPI:共建账户抽象未来的新一代 RPC 基础设施

在传统 RPC 服务板块上&#xff0c;开发者一直饱受故障风险、运行环境混乱等难题的折磨。实现 RPC 服务的去中心化&#xff0c;且保持成本优势和可扩展性&#xff0c;始终是区块链基础设施建设的重要命题之一。从 2018 年观察中心化 RPC 供应商服务现状开始&#xff0c;BlockPI…

Kubernetes 企业级高可用部署

1、Kubernetes高可用项目介绍 单master节点的可靠性不高&#xff0c;并不适合实际的生产环境。Kubernetes 高可用集群是保证 Master 节点中 API Server 服务的高可用。API Server 提供了 Kubernetes 各类资源对象增删改查的唯一访问入口&#xff0c;是整个 Kubernetes 系统的数…

使用断言抛异常操作

使用断言抛异常操作 常用方法 public static void isNull(Nullable Object object, String message) {if (object ! null) {throw new IllegalArgumentException(message);}}public static void notNull(Nullable Object object, String message) {if (object null) {throw n…

问道管理:股票打板风险大吗?怎么降低打板风险?

在股票市场上&#xff0c;一些出资者喜爱低吸&#xff0c;一些喜爱打板&#xff0c;那么&#xff0c;股票打板危险大吗&#xff1f;怎么下降打板危险&#xff1f;下面问道管理为大家准备了相关内容&#xff0c;以供参阅。 股票打板通常是指在个股涨停时买入&#xff0c;这种买入…

您可以购买 Banana Pi BPI-CM2 而不是 Raspberry Pi CM4。它提供什么?

最近&#xff0c;Banana Pi&#xff08;SINOVOIP&#xff09;推出了Banana Pi BPI-CM2系统级模块&#xff08;SoM&#xff09;。BPI-CM2 是类似于Raspberry Pi CM4 的计算模块&#xff0c;提供一系列令人印象深刻的功能。Banana BPI-CM2 SoM 采用Rockchip RK3568四核 Cortex-A5…

数据结构—排序

8.排序 8.1排序的概念 什么是排序&#xff1f; 排序&#xff1a;将一组杂乱无章的数据按一定规律顺序排列起来。即&#xff0c;将无序序列排成一个有序序列&#xff08;由小到大或由大到小&#xff09;的运算。 如果参加排序的数据结点包含多个数据域&#xff0c;那么排序往…

WebSocket服务端数据推送及心跳机制(Spring Boot + VUE)

一、WebSocket简介 HTML5规范在传统的web交互基础上为我们带来了众多的新特性&#xff0c;随着web技术被广泛用于web APP的开发&#xff0c;这些新特性得以推广和使用&#xff0c;而websocket作为一种新的web通信技术具有巨大意义。WebSocket是HTML5新增的协议&#xff0c;它的…

当你出差在外时,怎样轻松访问远程访问企业局域网象过河ERP系统?

文章目录 概述1.查看象过河服务端端口2.内网穿透3. 异地公网连接4. 固定公网地址4.1 保留一个固定TCP地址4.2 配置固定TCP地址 5. 使用固定地址连接 概述 ERP系统对于企业来说重要性不言而喻&#xff0c;不管是财务、生产、销售还是采购&#xff0c;都需要用到ERP系统来协助。…

快速解决Ubuntu 中 wine 程序 中文显示为方块/显示错误/无法显示中文(2023)

解决办法就是在创建prefix的命令行里加上LANG“zh_CN.UTF8” LC_ALL“zh_CN.UTF8”&#xff0c;并安装cjkfonts&#xff0c;即可。 1、生成prefix、安装cjk字体 以下是基本流程&#xff1a; 现在假定wine和winetricks已经装好&#xff0c; // 先创建一个prefix&#xff0c;按…

ArcGIS 利用cartogram插件制作变形地图

成果图 注&#xff1a;本图数据并不完全对&#xff0c;只做为测试用例 操作 首先需要下载一个插件cartogram 下载地址在这里 https://www.arcgis.com/home/item.html?idd348614c97264ae19b0311019a5f2276 下载完毕之后解压将Cartograms\HelpFiles下的所有文件复制到ArcGIS…

K8s实战4-使用Helm在Azure上部署Ingress-Nginx和Tokengateway

手动发布Ingress-Nginx 1 登录到aks(dfinder-gw-aks) az login az account set --subscription ${sub ID} az aks get-credentials --resource-group ${groupname} --name ${aks name} 2 下载 ingress-nginx-4.2.5.tgz curl -LO https://github.com/kubernetes/ingress-ngi…

【002】学习笔记之typescript的【任意类型】

任意类型 顶级类型&#xff1a;any类型和 unknown 类型 any类型 声明变量的时候没有指定任意类型默认为any任意类型都可以赋值给any&#xff0c;不需要检查类型。也是他的弊端如果使用any 就失去了TS类型检测的作用 unknown 类型 TypeScript 3.0中引入的 unknown 类型也被认为…

Tomcat 一次请求的生命周期

在使用 Tomcat 的时候&#xff0c;我们只需要在 Servlet 实现类中写我们的业务逻辑代码即可&#xff0c;不需要管 Socket 连接、协议处理要怎么实现&#xff0c;因为这部分作为不经常变动的部分&#xff0c;被封装到了 Tomcat 中&#xff0c;程序员只需要引入 Tomcat 中即可&am…

【C# 基础精讲】文件读取和写入

文件读取和写入是计算机程序中常见的操作&#xff0c;用于从文件中读取数据或将数据写入文件。在C#中&#xff0c;使用System.IO命名空间中的类来进行文件读写操作。本文将详细介绍如何在C#中进行文件读取和写入&#xff0c;包括读取文本文件、写入文本文件、读取二进制文件和写…

R语言APSIM模型进阶应用与参数优化、批量模拟实践技术

随着数字农业和智慧农业的发展&#xff0c;基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生…

Vue用JSEncrypt对长文本json加密以及发现解密失败

哈喽 大家好啊&#xff0c;最近发现进行加密后 超长文本后端解密失败&#xff0c;经过看其他博主修改 JSEncrypt原生代码如下&#xff1a; // 分段加密&#xff0c;支持中文JSEncrypt.prototype.encryptUnicodeLong function (string) {var k this.getKey();//根据key所能编…

初识Sentinel

目录 1.解决雪崩的方式有4种&#xff1a; 1.1.2超时处理&#xff1a; 1.1.3仓壁模式 1.1.4.断路器 1.1.5.限流 1.1.6.总结 1.2.服务保护技术对比 1.3.Sentinel介绍和安装 1.3.1.初识Sentinel 1.3.2.安装Sentinel 1.4.微服务整合Sentinel 2.流量控制 2.1.簇点链路 …

vscode用ssh远程连接linux

1、vscode是利用ssh远程连接linux的&#xff0c;所以首先确保vscode已经安装了这两个插件 2、点击左下角的连接 3、选择Connect to Host…… 5、按格式输入 ssh 主机名ip 比如我的&#xff1a;ssh mnt192.168.198.128 6、选择第一个打开配置文件&#xff0c;确保输入正确 7、…

主机防护的重要性和方式

01 主机防护的重要性 主机防护是网络安全的重要组成部分。在互联网时代&#xff0c;网络攻击成为了一种常见的威胁&#xff0c;而主机防护则是保护计算机系统免受网络攻击的重要手段。 主机防护可以防范各种网络攻击&#xff0c;如病毒、木马、黑客攻击等&#xff0c;从而保…