Linux学习之路 -- systemV进程通信 -- 消息队列和信号量(简单介绍)

一、简介:

        System V进程通信(System V IPC)是一组在Unix和类Unix操作系统中用于进程间通信的机制。这些机制在System V Release 2中首次引入,并在POSIX标准中得到部分采纳。System V IPC主要包括以下几种通信方式:

消息队列(Message Queues):

消息队列允许一个或多个进程写入或读取消息。消息队列可以看作是一个消息链表,每个消息都有一个类型和一个优先级。进程可以向队列中添加消息,也可以从队列中读取消息。
信号量(Semaphores):

信号量是一种用于同步进程的机制。它可以用来控制多个进程对共享资源的访问。System V信号量分为两种:二进制信号量和计数信号量。信号量通过操作原语如P(等待)和V(信号)来工作。
共享内存(Shared Memory):

共享内存允许两个或多个进程共享一段内存区域。这是最快的IPC方式,因为数据不需要在客户和服务器进程间复制,而是直接在内存中共享。共享内存通常与信号量结合使用,以同步对共享内存的访问。

2、消息队列

1、相关原理的简单介绍

进程之间的通信都要让两个进程看到同一块资源,在消息队列这种通信方式下,就是让两个进程在内核当中看到同一个队列。两个进程只需要向队列中写入特定类型的数据,由另外一个进程读取这个类型的数据即可。

2、相关接口介绍

<1>msgget

申请一个消息队列,参数key和shmget的key作用一样,都是标识队列的唯一性,参数msgflg和shmget的参数shmflg是一样的,一般常用的有两种参数 IPC_CREAT和IPC_EXCL(具体作用不赘述),成功返回msgid,失败返回-1,其返回值msgid可以作为用户层面上区分队列的标识。

<2>msgctl

该系统调用用来对消息队列进行控制,msqid为msgget的返回值。cmd参数表示控制命令,常用的为以下三个:

        IPC_STAT:获取消息队列的各种属性。
        IPC_SET:对消息队列的中的属性进行设置。
        IPC_RMID:删除消息队列。(如果在终端上,我们可以使用ipcrm -q + msgid来对消息队列进行删除)。
struct msqid_ds* buf是一个输出型参数,这个结构体和struct shmid_ds几乎完全一样,该结构体中的成员都是消息队列的一些属性进行描述。

其中在结构体struct ipc_perm中可以获取key值的大小。

<3>msgsnd&&msgrcv

msgsnd表示向消息队列中发送消息,msgrcv表示向消息队列中接受信息。

第一个参数就是msgget的返回值,我们直接传入即可。在第二个参数上,两个系统调用的传参稍稍有点差异,首先我们都需要定义一个struct msgbuf;

在这个结构体中,第一个成员是消息的类型,第二个成员是具体的消息数据。在msgsnd系统调用时我们需要将该结构体内的数据手动补充完成后,再传入数据,在msgrcv中不用,只要在定义好后,传入指针即可。第三个参数就是结构体中mtext数据的大小。而msgflg这个参数我们直接设置为0,表示默认就可以了。msgtyp表示需要接受的消息队列的类型。

3、信号量

1、简单的原理介绍

在正式介绍信号量之前,我们需要了解一些预备知识:

<1>对一个共享资源的保护,是在多执行流场景下的一个常见问题,这是因为在多个执行流访问同一块共享资源时,可能会造成一些问题,比如数据不一致等。目前,管道通信是系统帮我们将管道这个共享资源进行保护,而共享内存是不会被OS主动保护的,需要用户去手动保护。、

<2>为了保护共享资源,我们一般有两种机制,我们称为互斥和同步机制。互斥,我们可以理解成当一名同学去食堂打饭时,打饭的阿姨只能给这一名同学打饭,而不能给其他同学打的这种状态,我们就可以理解成互斥状态。而同步,我们可理解成一名同学打饭,打饭完成后立马吃完,一直站在窗口上,不断让阿姨打饭,这样就会造成其他同学压根打不到饭。所以规定一个同学打完饭后必须重新站到队尾,让每个同学都能打到饭,这种机制,我们就称为同步。

<3>被保护起来的,任意时刻只允许一个执行流访问的公共资源,我们称为临界资源,访问临界资源的代码,我们就叫做临界区,其他区域叫非临界区。

<4>原子性:操作对象的时候,只有两种情况,要么还没开始,要么已经结束。

注:由于信号量涉及的内容大多与多线程有关,所以下面只做简单的介绍。

我们以电影票买票来引入信号量的概念,当我们去看电影时,一般都需要购买电影票,只有买了电影票,才能在电影的时候拥有座位。这个座位实际上是就属于电影院的一种资源,我们买票的过程就是对资源进行预定,预订以后,虽然资源现在没有被我持有,但是在未来的时间段内,只要我想,就可以使用这一部分资源。

而电影院,就需要合理的卖票 -- 有多少资源,我们就卖多少票,而电影院需要确保每一份资源都不会出现并发访问的情况,也就是多人持有一张票的情况。虽然我们将电影院看成一个整体使用(也就是只有一张票)情况下,不容易出现问题,但是资源的利用效率太低。为了提高资源的利用率,我们就在电影院中安排了很多座位,也就是将电影院资源分成很多小资源。而当进程进来申请资源时,我们需要防止申请进程数大于资源数量的情况。为了避免该情况的发生,我们就需要限制进来的进程数,合理地分配资源。

如何限制进来地进程数呢?这就需要提到信号量了,信号量本质上是一个计数器,用于描述临界资源地一个计数器(我们用int count 这个变量来描述这个计数器)。

而我们的进程申请信号量,就相当于买票预定,只要信号量申请成功(count -- ),就一定有你的资源。如果我们申请失败,就必须继续等,只有等待申请成功,才能进行下一步。申请完成后,我们就可以进行访问资源,访问完成后,就可以释放信号量(count ++)。申请信号量和释放信号量的过程就是在保护临界资源。 

这里有一个问题,那就是在多进程场景下中,我们可不可以用int来实现信号量呢? 答案是不行,因为在进程之间,整型变量无法共享。不同的进程需要看到同一块计数器资源。另一个原因是因为整型的加减不是原子的,在我们将整型的加减代码转换成汇编代码,我们就会发现加减代码回转成多条汇编语句,只有一条汇编语句才能绝对保证原子性(了解即可)。

上面我们申请信号量和释放信号量,都是多进程/线程必须遵守的规定。所有进程访问临界资源时,都必须先申请信号量,这就说明所有的进程都要看到同一个信号量资源,那么信号量就是一块共享资源,为了确保这个信号量的安全,OS就必须确保信号的申请和释放操作是原子的。而申请信号量我们称为P操作,释放信号量我们称为V操作,和起来我们称为PV操作。

当我们的信号为1时,这就是互斥,而这个二元信号量也是就是一把锁。

2、信号量的相关接口:

当我们申请信号量时,是可以申请申请多个信号量,注意区分申请一个大小为n的信号量。

<1>semget

该系统调用的接口用于创建一个信号量集,第一个参数key和消息队列、共享内存的key无异,第二个参数表示想申请几个信号量,第三个参数和消息队列的shmget与msgget中的第三个参数无异,我们一般使用IPC_CREAT和IPC_EXCL。如果成功返回一个非负整数(semid),用于标识信号量集,失败返回-1。

<2>semctl

该接口用于控制创建的信号量集,第一个参数,我们返回semid即可。第二个参数,表示要对信号集中哪一个参数进行调整。第三个参数表示要对哪些信号量进行哪些操作。常见的有IPC_STAT、IPC_RMID、IPC_SET等等,和shmctl和msgctl的选项功能一样。" .... "这是一个可选的参数,它是一个union semun类型的变量,包含了与特定命令相关的附加信息。某些semctl命令需要额外的数据来执行操作,比如设置信号量的值、获取信号量集的权限等。这个参数提供了这些数据。

<3>semop

该接口用于表示对特定信号量执行操作。

第一个参数表示要对哪一个信号集进行操作,第二个参数需要我们自己定义一个结构体struct sembuf,里面包含的成员有如下几个:

第一个成员表示要对信号量集(我们可以看成一个数组)的哪一个进行操作,该参数就是信号量集的下标,第二个成员表示要进行P操作还是V操作,-1表示要进行P操作,1表示进行V操作。第三个成员表示操作标识,默认设为0。

第三个参数指定信号操作的数量,也就是操作几次。

4、system V进程通信的原理

通过上面的介绍,我们其实可以发现,共享内存,消息队列这三个通信方式有很多的相似之处,这是OS故意为之,目的就是为了更好地管理这些IPC资源( Inter-Process Communication)。为了管理好这些资源,OS肯定需要通过结构体对这些资源进行描述和组织。

在内核中,存在一个ipc_ids的结构体管理ipc资源,其中包含了一个entries指针,这个指针指向ipc_id_ary,在ipc_id_ary中有一个柔性数组,存放了struct kern_ipc_perm* 的指针,struct kern_ipc_perm是在内核中管理这些ipc资源属性的结构体。每当我们创建ipc资源时,OS就把描述对应资源的结构体指针放入该柔性数组。msgid、shmid、semid其实就是对应的数组下标,如果下标过大,id会进行回绕。这里操作系统将所有的指针都看成kern_ipc_perm,当OS需要对特定ipc资源进行操作时,直接把对应的指针强转为对应的类型即可,这里访问ipc资源可以通过key来实现(key的地址就是每个结构体的地址,通过key就可以直接访问结构体)。为了获取对应的类型,OS会在ipc_perm的mode成员中加入数据类型。我们一般可以用位操作定义不同的宏,通过宏来表示不同的类型。

但是由于其设计理念和Liunx一切皆文件的设计初衷稍有偏差,导致这种通信方式已经被边缘化。感谢阅读,如有不对之处,还望各位大佬指正。

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

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

相关文章

数据结构(三)——双向链表,循环链表,内核链表,栈和队列

双链表 产生原因&#xff1a;单链表只有一个指向后继的指针&#xff0c;如果要访问某节点的前驱结点&#xff0c;只能从头遍历&#xff0c;也就是访问后继节点的时间复杂度为1&#xff0c;访问前驱结点的时间复杂度为n。 而引入双链表使得在插入、删除的…

Redis_AOF持久化

AOF持久化 在AOF持久化的过程中&#xff0c;会以日志的方式记录每个redis“写”命令&#xff0c;并且redis服务器重启时重新执行AOF日志文件中的命令&#xff0c;从而达到“恢复数据”的效果 AOF故障恢复 当redis因发生故障而重启时&#xff0c;redis服务器会按照如下步骤根据…

VMware安装中标麒麟操作系统V7.0

1 说明 由于未来的工作需要&#xff0c;今天开始学习DM8数据库&#xff0c;搭建一个实验环境供学习实操使用。配置要求如下&#xff1a; 直接一步到位&#xff0c;在信创平台安装DM8数据库&#xff0c;这里选择了耳熟能详的中标麒麟操作系统&#xff0c;版本为V7.0。以前从未安…

vue手机端 搜索框调起带搜索键盘,点击确认自动关闭

效果如下图 步骤&#xff1a; 1.html,所需配置参数都在下图 <el-form :inline"true" :mode"serchFormf" class"searchForm" action"javascript:return true;"><el-form-item label"" ><el-inputsize"…

【linux002】目录操作命令篇 - ls 命令

文章目录 1、基本用法2、常见选项3、举例演示4、注意事项 ls 命令在 Linux 中用于列出目录内容。它有许多选项和参数可以用来调整显示的格式和内容。 1、基本用法 ls [选项] [文件或目录]2、常见选项 -a 或 --all&#xff1a;显示所有文件&#xff0c;包括以点.开头的隐藏文件…

java 切面日志打印出参入参

切面Controller出入参日志打印 项目结构 切面日志对controller下所有的方法生效 切面代码 Slf4j Aspect Component public class ControllerLogAspect {// 定义一个切点&#xff0c;拦截所有Controller层的public方法Before("execution(public * com.jzt.market.cont…

进程和线程(操作系统八股文part2)

一个操作系统的进程和线程部分的笔记&#xff0c;大部分来源于&#xff1a;小林coding和Javaguide&#xff0c;以及操作系统黑书。 进程和线程 什么是进程 运行中的程序叫进程**&#xff08;Process&#xff09;**。 进程是资源分配的最小单位&#xff0c;线程是执行的最小…

【QT】学习笔记:枚举桌面窗口句柄

在 Qt 中&#xff0c;虽然 Qt 本身没有直接提供枚举桌面窗口的 API&#xff0c;但可以通过调用 Windows API 来实现枚举桌面上所有窗口的句柄&#xff0c;包括子窗口以及子窗口与父窗口的关系。我们可以使用 Windows 的 EnumWindows 和 EnumChildWindows 函数来枚举所有顶层窗口…

K8S声明式的管理方式

一、K8S声明式的管理方式&#xff1a; 1、适合对资源的修改操作 2、声明式管理依赖于yaml文件&#xff0c;所有的内容都在yaml文件中声明 3、编辑好的yml文件还是要靠陈述式命令发布到K8S集群中 二、K8S中支持三种声明式的资源管理方式&#xff1a; 1、deployment格式&…

【YOLO系列】YOLO算法改进史

目录 前言YOLOv1YOLOv2YOLOv3YOLOv4YOLOv5YOLOv6YOLOv7YOLOv8YOLOv9YOLOv10对比待更新 前言 YOLO&#xff08;You Only Look Once&#xff09;是一种革命性的目标检测算法&#xff0c;以其快速和高效的性能而闻名。自2015年YOLOv1的首次推出以来&#xff0c;YOLO系列已经经历了…

Linux常见基础命令

Linux基础 初级学习阶段需要了解的知识一、Linux基础命令查阅命令帮助信息1.man2.help Linux命令的基本实用目录操作文件内容操作查看某文件下的用户操作日志压缩和解压缩sudo用户权限操作用户权限操作TOP文件安装 上一篇 VMware安装linux环境 初级学习阶段需要了解的知识 1.…

音视频入门基础:WAV专题(7)——FFmpeg源码中计算WAV音频文件每个packet的size值的实现

一、引言 从文章《音视频入门基础&#xff1a;WAV专题&#xff08;6&#xff09;——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道&#xff0c;通过FFprobe命令可以显示WAV音频文件每个packet&#xff08;也称为数据包或多媒体包&#xff09;的信息&#xff0…

YOLO环境搭建备忘教程

注&#xff1a;该文本是在完成anaconda、pycharm后进行的过程&#xff0c;请注意&#xff01; 1、conda下创建一个新环境&#xff1a; conda create -n 环境名称 python版本号 #注意各类代码的具体Python版本号 conda create -n Pysidey6 python3.8.1 #注意&#xff1a;3…

rk3566刷机openWrt

文章目录 说明硬件工具软件工具简介驱动安装运行刷机工具配置bootloader和刷机固件连接设备 设备未识别执行刷机执行效果访问openwrt变砖问题 说明 本教程由csdn缘友一世原创&#xff0c;经过亲身实践总结&#xff0c;可以保证有效性&#xff01; 硬件工具 Window电脑(windo…

KEYSIGHT是德 Infiniium EXR系列 示波器

Infiniium EXR系列 示波器 苏州新利通 引言 概述 Infiniium EXR系列 出色的信号完整性让信号纤毫毕现 该系列的所有型号都集成了一个 10 位 ADC&#xff0c;并且在所有通道上同时提供 16 GSa/s 的采样率。高分辨率 ADC 的效用取决于示波器的前端底噪是否足够低以提供与之匹…

二叉搜索树进阶之红黑树

前言&#xff1a; 在上文我们已经学习了AVL树的相关知识以及涉及的四种旋转的内容&#xff0c;但是AVL树追求平衡导致旋转操作过多&#xff0c;一些情况下影响性能&#xff0c;由此我们就来了解一下二叉搜索树的另外一个分支&#xff0c;红黑树。 &#xff08;倘若对旋转知识…

学习笔记——后端项目中的相关技术 【随时更新】

文章目录 1. Session 共享1.0 cookie和session的工作流1.1 Cookie范围1.2 为什么要共享&#xff1f;1.3 如何共享存储1.4 session共享实现 2. 缓存的实现2.1 缓存分类2. 2 Redis 缓存实现2.1.1 Spring data redis&#xff08;推荐使用&#xff09;2.1.2 Redis 的数据结构&#…

C++----简单了解vector

大家好&#xff0c;今天我们来讲讲与string相似的向量类型。之所以说他们是相似的原因是他们其中的数据类型有些效果都是一样的。当然大家不能说&#xff0c;既然是差不多的干嘛还有一个这个啊。不如直接用string就可以了。当然世界名言存在即合理。既然我们都能想到的东西&…

金融知识普及月答题活动

金融知识普及月答题活动 关键词&#xff1a;金融安全、风险防范、金融常识、反诈宣传 推荐功能&#xff1a;答题、倡议书 宣传角度&#xff1a; 1. 普及金融知识&#xff1a;讲解货币、信用、利率、汇率等基本金融概念&#xff0c;以及储蓄、贷款、信用卡、保险等常见金融产…

Unity 图表插件Xcharts的一些坑

XY轴、图例文字不清晰。 2种方法解决 1&#xff1a;老套路&#xff0c;先放大再缩小&#xff0c;像素点多了就清晰了。 2&#xff1a;设置一个单独渲染的UI相机&#xff0c;把canvs所在的UI层级使用深度相机单独渲染,另一个选剔除UI的纯色或天空盒。同时&#xff0c;把改Canva…