Linux进程间通信(三)-----System V消息队列

消息队列的概念及原理

        消息队列实际上就是在系统当中创建了一个队列,队列当中的每个成员都是一个数据块,这些数据块都由类型和信息两部分构成,两个互相通信的进程通过某种方式看到同一个消息队列,这两个进程向对方发数据时,都在消息队列的队尾添加数据块,这两个进程获取数据块时,都在消息队列的队头取数据块。

其中消息队列当中的某一个数据块是由谁发送给谁的,取决于数据块的类型。

总结一下:

  1. 消息队列提供了一个从一个进程向另一个进程发送数据块的方法。
  2. 每个数据块都被认为是有一个类型的,接收者进程接收的数据块可以有不同的类型值。
  3. 和共享内存一样,消息队列的资源也必须自行删除,否则不会自动清除,因为system V IPC资源的生命周期是随内核的。

消息队列数据结构

当然,系统当中也可能会存在大量的消息队列,系统一定也要为消息队列维护相关的内核数据结构。

消息队列的数据结构如下:

struct msqid_ds {
	struct ipc_perm msg_perm;
	struct msg *msg_first;      /* first message on queue,unused  */
	struct msg *msg_last;       /* last message in queue,unused */
	__kernel_time_t msg_stime;  /* last msgsnd time */
	__kernel_time_t msg_rtime;  /* last msgrcv time */
	__kernel_time_t msg_ctime;  /* last change time */
	unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */
	unsigned long  msg_lqbytes; /* ditto */
	unsigned short msg_cbytes;  /* current number of bytes on queue */
	unsigned short msg_qnum;    /* number of messages in queue */
	unsigned short msg_qbytes;  /* max number of bytes on queue */
	__kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
	__kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
};

可以看到消息队列数据结构的第一个成员是msg_perm,它和shm_perm是同一个类型的结构体变量,ipc_perm结构体的定义如下:

struct ipc_perm{
	__kernel_key_t  key;
	__kernel_uid_t  uid;
	__kernel_gid_t  gid;
	__kernel_uid_t  cuid;
	__kernel_gid_t  cgid;
	__kernel_mode_t mode;
	unsigned short  seq;
};

记录一下:共享内存的数据结构msqid_dsipc_perm结构体分别在/usr/include/linux/msg.h和/usr/include/linux/ipc.h中定义。

消息队列的创建

创建消息队列我们需要用msgget函数,msgget函数的函数原型如下:

int msgget(key_t key, int msgflg);

说明一下:

  1. 创建消息队列也需要使用ftok函数生成一个key值,这个key值作为msgget函数的第一个参数。
  2. msgget函数的第二个参数,与创建共享内存时使用的shmget函数的第三个参数相同。
  3. 消息队列创建成功时,msgget函数返回的一个有效的消息队列标识符(用户层标识符)。

消息队列的释放

释放消息队列我们需要用msgctl函数,msgctl函数的函数原型如下:

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

说明一下:
msgctl函数的参数与释放共享内存时使用的shmctl函数的三个参数相同,只不过msgctl函数的第三个参数传入的是消息队列的相关数据结构。

向消息队列发送数据

向消息队列发送数据我们需要用msgsnd函数,msgsnd函数的函数原型如下:

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

msgsnd函数的参数说明:

  • 第一个参数msqid,表示消息队列的用户级标识符。
  • 第二个参数msgp,表示待发送的数据块。
  • 第三个参数msgsz,表示所发送数据块的大小
  • 第四个参数msgflg,表示发送数据块的方式,一般默认为0即可。

msgsnd函数的返回值说明:

  • msgsnd调用成功,返回0。
  • msgsnd调用失败,返回-1。

其中msgsnd函数的第二个参数必须为以下结构:

struct msgbuf{
	long mtype;       /* message type, must be > 0 */
	char mtext[1];    /* message data */
};

注意: 该结构当中的第二个成员mtext即为待发送的信息,当我们定义该结构时,mtext的大小可以自己指定。

从消息队列获取数据

从消息队列获取数据我们需要用msgrcv函数,msgrcv函数的函数原型如下:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgrcv函数的参数说明:

  • 第一个参数msqid,表示消息队列的用户级标识符。
  • 第二个参数msgp,表示获取到的数据块,是一个输出型参数。
  • 第三个参数msgsz,表示要获取数据块的大小
  • 第四个参数msgtyp,表示要接收数据块的类型。

msgrcv函数的返回值说明:

  • msgsnd调用成功,返回实际获取到mtext数组中的字节数。
  • msgsnd调用失败,返回-1。

System V信号量

信号量相关概念

  • 由于进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系叫做进程互斥
  • 系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源
  • 在进程中涉及到临界资源的程序段临界区
  • IPC资源必须删除,否则不会自动删除,因为system V IPC的生命周期随内核。

信号量数据结构

在系统当中也为信号量维护了相关的内核数据结构。

信号量的数据结构如下:

struct semid_ds {
	struct ipc_perm sem_perm;       /* permissions .. see ipc.h */
	__kernel_time_t sem_otime;      /* last semop time */
	__kernel_time_t sem_ctime;      /* last change time */
	struct sem  *sem_base;      /* ptr to first semaphore in array */
	struct sem_queue *sem_pending;      /* pending operations to be processed */
	struct sem_queue **sem_pending_last;    /* last pending operation */
	struct sem_undo *undo;          /* undo requests on this array */
	unsigned short  sem_nsems;      /* no. of semaphores in array */
};

信号量数据结构的第一个成员也是ipc_perm类型的结构体变量,ipc_perm结构体的定义如下:

struct ipc_perm{
	__kernel_key_t  key;
	__kernel_uid_t  uid;
	__kernel_gid_t  gid;
	__kernel_uid_t  cuid;
	__kernel_gid_t  cgid;
	__kernel_mode_t mode;
	unsigned short  seq;
};

进程互斥

        进程间通信通过共享资源来实现,这虽然解决了通信的问题,但是也引入了新的问题,那就是通信进程间共用的临界资源,若是不对临界资源进行保护,就可能产生各个进程从临界资源获取的数据不一致等问题。

        保护临界资源的本质是保护临界区,我们把进程代码中访问临界资源的代码称之为临界区,信号量就是用来保护临界区的,信号量分为二元信号量和多元信号量。

        比如当前有一块大小为100字节的资源,我们若是一25字节为一份,那么该资源可以被分为4份,那么此时这块资源可以由4个信号量进行标识。

信号量本质是一个计数器,在二元信号量中,信号量的个数为1(相当于将临界资源看成一整块),二元信号量本质解决了临界资源的互斥问题,以下面的伪代码进行解释:

        根据以上代码,当进程A申请访问共享内存资源时,如果此时sem为1(sem代表当前信号量个数),则进程A申请资源成功,此时需要将sem减减,然后进程A就可以对共享内存进行一系列操作,但是在进程A在访问共享内存时,若是进程B申请访问该共享内存资源,此时sem就为0了,那么这时进程B会被挂起,直到进程A访问共享内存结束后将sem加加,此时才会将进程B唤起,然后进程B再对该共享内存进行访问操作。

        在这种情况下,无论什么时候都只会有一个进程在对同一份共享内存进行访问操作,也就解决了临界资源的互斥问题。

        实际上,代码中计数器sem减减的操作就叫做P操作,而计数器加加的操作就叫做V操作,P操作就是申请信号量,而V操作就是释放信号量。

system V IPC联系

        通过对system V系列进程间通信的学习,可以发现共享内存、消息队列以及信号量,虽然它们内部的属性差别很大,但是维护它们的数据结构的第一个成员确实一样的,都是ipc_perm类型的成员变量。

这样设计的好处就是,在操作系统内可以定义一个struct ipc_perm类型的数组,此时每当我们申请一个IPC资源,就在该数组当中开辟一个这样的结构。

也就是说,在内核当中只需要将所有的IPC资源的ipc_perm成员组织成数组的样子,然后用切片的方式获取到该IPC资源的起始地址,然后就可以访问该IPC资源的每一个成员了。

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

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

相关文章

【C++ QT项目2】——高仿安信可串口调试助手

【C QT项目2】——高仿安信可串口调试助手 1. 项目概述2. 项目UI设计3. 串口通信核心代码开发3.1 QSerialPort介绍及示例3.2 扫描系统串口3.3 数据的收发3.4 定时发送(QT定时器)3.5 HEX显示与发送 4. 串口调试助手功能的优化4.1 串口的实时扫描4.2 获取系…

2024.2.15 模拟实现 RabbitMQ —— 消息持久化

目录 引言 约定存储方式 消息序列化 重点理解 针对 MessageFileManager 单元测试 小结 统一硬盘操作​​​​​​​ 引言 问题: 关于 Message(消息)为啥在硬盘上存储? 回答: 消息操作并不涉及到复杂的增删查改消…

对比@Resource和@Autowired

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Resource和Autowired概述 在Java的Spring框架中,Resource和Autowired都是用于实现依赖注入(Dependency Injection, DI)的重要注解。依赖…

【机器学习笔记】11 支持向量机

支 持 向 量 机 ( Support Vector Machine,SVM ) 支 持 向 量 机 是 一 类 按 监 督 学 习 ( supervisedlearning)方式对数据进行二元分类的广义线性分类器(generalized linear classifier),其…

Python教程(26)——Python迭代器和生成器详解

迭代器 Python中的迭代器是一种对象,它可以迭代(遍历)一个可迭代对象(比如列表、元组或字符串)的元素。迭代器用于实现迭代器协议,即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次调…

大模型- 检索增强七宗罪

前言 地址:https://arxiv.org/pdf/2401.05856.pdf 标题:Seven Failure Points When Engineering a Retrieval Augmented Generation System 这篇论文介绍了如何设计一个检索增强生成系统(RAG),作者通过对三个不同领域…

人工智能专题:通过AI转变保险(英译中)

今天分享的是人工智能系列深度研究报告:《人工智能专题:通过AI转变保险(英译中)》。 (报告出品方:VIEWPOINT) 在新时代释放数据的力量 在数据和人工智能 ( AI ) 融合的…

Mac配置Python3最简单的方法

此文介绍Mac用Anaconda配置Python3 达成效果 能让你目前只装有Python2的Mac装上Python3,同时拥有很多科学计算库 anaconda介绍 anaconda 是一个python的发行版,包括了python和很多常见的软件库, 和一个包管理器conda。常见的科学计算类的库都包含在里…

Java集合篇之深入解析ArrayList,这六问你答的上来吗?

写在开头 开年第一篇,先祝各位新的一年身体健康,学业有成,事业有成哈,春节期间就是咔咔乱吃,咔咔乱玩,把学习都抛一边子去了,已经9天没有学习了,深深的懊悔,从今天开始&…

人工智能学习与实训笔记(八):百度飞桨套件使用方法介绍

人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 八、百度飞桨套件使用 8.1 飞桨预训练模型套件PaddleHub 8.1.1 一些本机CPU可运行的飞桨预训练简单模型(亲测可用) 8.1.1.1 人脸检测模型 8.1.1.2 中文分词模型 8.1…

2-17作业

#!/bin/bash read zifu case $zifu in [[:lower:]]) echo "小写字母" ;; [0-9]) echo "是数字字符" ;; [[:upper:]]) echo "是大写字母" ;; esac #!/bin/bash arr(ls ~) len${#arr…

Codeforces Round 926 (Div. 2)(A,B,C,D,E,F)

这场还是很有含金量的,B题开始就有难度了,B是个推结论的题,C要推结论然后递推,D题是有点难的树上DP(主要是状态转移方程不好写),E题是个二进制预处理然后状压DP,F题是个数论&#xf…

使用Apache ECharts同时绘制多个统计图表

目录 1、介绍 2、相关知识 3、代码 4、效果 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。 …

Linux第59步_“buildroot”构建根文件系统第1步_生成rootfs.tar和rootfs.ext4以及通过nfs下载测试

学习安装“buildroot”,通过配置构建根文件系统,编译生成rootfs.tar和rootfs.ext4,以及通过nfs下载测试。 1、了解学习目的: 1)、获取“buildroot”安装包; 2)、使用“buildroot”构建根文件系统; 3)、…

【论文精读】Latent Diffusion

摘要 Diffusion models(DMs)被证明在复杂自然场景的高分辨率图像合成能力优于以往的GAN或autoregressive (AR)transformer。作为基于似然的模型,其没有GAN的模式崩溃和训练不稳定问题,通过参数共享&#xf…

五分钟搭建本地大数据集群

引言 刚接触大数据以及部分接触大数据多年的伙伴可能从来没有自己搭建过一套属于自己的大数据集群,今天就花点时间聊聊怎么快速搭建一套属于自己、且可用于操作、调试的大数据集群 正文 本次搭建的组件都有以下服务以及对应的版本 hadoop(3.2.4&…

人工智能学习与实训笔记(四):神经网络之NLP基础—词向量

人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 四、自然语言处理 4.1 词向量 (Word Embedding) 4.1.1 词向量的生成过程 4.1.2 word2vec介绍 4.1.3 word2vec:skip-gram算法的实现 4.2 句向量 - 情感分析 4.2.1 LSTM (Long S…

嵌入式Qt Qt中的字符串类

一.Qt中的字符串类 QString vs string&#xff1a; QString在Qt库中几乎是无所不在的 所有的Qt图形用户组件都依赖于QString 实验1 &#xff1a;QString 初体验 #include <QDebug> void Sample_1() {QString s "add";s.append(" "); // &q…

为什么MySQL不建议使用TEXT字段?

当我们深入探讨“为什么MySQL不建议使用TEXT字段&#xff1f;”这一问题时&#xff0c;可以从一下多个方面来详细理解这个问题&#xff1a; 1. 性能问题 性能问题是MySQL不建议使用TEXT字段的一个重要原因。TEXT字段通常以外部存储方式保存&#xff0c;而不是像固定长度或可变…

边缘计算第二版施巍松——第8章边缘计算系统实例

8.1边缘计算系统概述 1.Cloudlet 架构&#xff1a;移动设备-Cloudlet-云 cloudlet也可以像云一样为用户提供服务&#xff0c;Cloudlet离移动设备只有一跳的距离&#xff0c;具有物理距离的临近性&#xff0c;可以保证实时反馈时延低&#xff0c;又可以利用局域网的高带宽优势&…