进程间通信之system V共享内存

news2024/11/24 8:49:12

目录

🎞一、共享内存---shm

1.1shmget

①ftok得到一个key

②shmget得到shm

③shm的性质

1.2 shmctl

①ipcrm

②shmctl

 1.3shmat&&shmdt

①shmat

②shmdt

 1.4通过shm完成进程间通信

 1.5shm的特点

①shm共享内存的优点

②shm的缺点

1.6shm的内核结构

①内核

②shm大小的问题

🎞二、消息队列&&信号量

2.1消息队列

2.2信号量

🎞一、共享内存---shm

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

共享内存的示意图:

 共享内存是OS为了方便本地进程间进行通信而专门在物理内存开辟的一块供进程间通信的区域。

通过上图我们看到共享内存开辟一块空间后,两个进程得到它的地址,这样就能看到同一份资源,从而对资源进行操作。

1.1shmget

 

接口参数注释:

size: 想要申请的共享内存空间的大小。

shmflg:通常设置为两种选项。选项的本质是宏,通过位图的方式,传二进制的方式传进去的。类似于open接口的flags选项。

key:唯一性标识共享内存。以便进程找到相同的共享内存。

shmflg的常用选项是IPC_CREAT和IPC_EXCL

IPC_CREAT:如果想创建的指定的共享内存不存在,就创建;如果存在,就获取它。也就是说这个选项的作用在于前面创建了指定共享内存后就不必再创建,直接获取即可。

IPC_EXCL:这个选项无法单独使用。它是配合IPC_CREAT使用的。IPC_CREAT | IPC_EXCL;如果不存在就创建共享内存;如果存在就出错返回

IPC_EXCL选项的意义在于如果创建成功了,那么一定是一个新的共享内存。如果出错了,说明已经存在一个共享内存(shm)

key参数的作用是唯一性标识shm。为什么要用它来唯一性标识呢?因为首先它是让我们要进行通信的进程通过key找到相同的shm。而且这里还有一个概念就是OS中一定可能同时存在很多的shm一个shm一个唯一的key不仅方便我们查找也方便OS管理shm

①ftok得到一个key

借助ftok接口我们可以得到一个key

 

这个函数的意义在于将一个路径名和项目的标识符转换成一个system V的IPC key

传进来的字符串pathname和字符数据proj_id,通过算法转化出一个key

那么我们只需要通过ftok()函数,传递相同的pathname和proj_id,那么就能得到相同的key,通过key就能找到相同的shm

 shm_client和shm_server调用同一函数,函数的参数都一样,所以生成的key值也是一样的,不过这个key值具体是多少不重要。关键是它能唯一性标识最重要。

那么得到key之后,我们就可以调用shmget()函数来得到shm了。

②shmget得到shm

因为是一个进程创建,另一个进程获取,我们调用shmget函数的前两个参数,key值和shm的大小都是一样的,无非就是第三个参数选项的不同。所以我们可以封装成函数。

 

 shm_server创建shm,shm_client获取shm。运行成功后,我们得到一个shmid。这个shmid是该共享内存段的标识码。那么问题来了,我们之前生成过key来标识shm,这里的shmid再来标识是否多此一举呢?

③shm的性质

这里要回到OS层面来分析。OS是如何管理shm呢?先描述再组织。shm==物理内存块+相关属性。每申请一块shm,除了申请额定大小的空间,还要生成一个管理对象,记载它的相关属性以便管理。在OS层面,每个shm都有一个独特的key来标记,方便它管理。这个key是要设置进shm的描述属性中的。用来标识该shm在内核中的唯一性。

而shmid则是用户层面方便我们对shm进行管理的!这里shmid和key的服务对象不同但都是用来标识shm,这就类似于文件描述符fd和inode的关系!

那么谈完key的属性。我们再来看一下shm资源有什么属性:

当我们已经创建了shm,再次运行时,就会告诉我们文件已经存在。这里我们注意到进程已经结束,而IPC资源依旧被占用

 那么这里要介绍指令ipcs -m 查看shm资源。

我们发现OS中确实仍旧存在shm资源shm的生命周期是随着OS的,而不是随着进程的

这种特性是system V所特有的,我们的system V的共享内存,消息队列和信号量都有这样的特点。

ipcs指令用来查看system V资源

其中消息队列查看加上-q选项。信号量查看加上-s选项。

 

1.2 shmctl

①ipcrm

那么既然进程结束仍旧存在,如何删除呢?

指令:ipcrm -m  shmid

ipcrm -m指令加上指定资源的shmid即可删除。

 

②shmctl

上面是指令级的操作,代码层面要使用OS提供的接口shmctl

 shmctl用来对shm进行控制,包括删除。

参数:

shmid:shmget返回的共享内存标志码;

cmd:将要采取的动作(有三个可取值)

buf:指向一个保存着共享内存的模式状态和访问权限的数据结构。

返回值:成功返回0,失败返回-1.

cmd具体的三个命令:

IPC_STAT:shmid_ds结构中的数据设置为shm的当前关联值。

IPC_SET:在进程有足够权限的前提下,把shm的当前关联值设置为shmid_ds数据结构中给出的值。

IPC_RMID:删除shm

那么shmid_ds是什么结构呢?

shmid_ds内部维护着shm的相关属性。如果我们要得到shmid_ds结构维护的属性,需要使用IPC_STAT指令并把相关结构的指针给buf。通过buf即可访问。

删除shm

 

这样我们的代码就变成了创建成功shm后,5s后删除它,可以通过shell窗口监视:

 

 1.3shmat&&shmdt

①shmat

我们已经完成了shm的创建和删除,接下来使用shmat函数来让我们的进程得到共享内存的地址。

shmid:想和哪个shm关联。

shmaddr:想把shm映射到哪一个地址空间中,一般设置为nullptr

shmflg:默认读写,设置为0.

返回值:成功返回一个指针,指向shm的地址;失败则返回-1.

创建成功,5s后,挂接成功,再过5s,成功删除:

在演示中,我们看到,并没有如我们所愿挂接成功,而是报错:permisson deny。美没有权限。

 

 所以,在创建时我们要给上shm的权限:

给上权限0600,只有拥有者有权限。

再来看一下:

 可以看到attach成功,并且可以看到,挂接成功时的属性。

②shmdt

 当不再使用的时候,不要直接删除而是去关联,去关联并不是删除shm,二而是把进程和shm的映射关系去除:

 shmaddrshmat()的返回值。

返回值:成功就是0,失败就是-1.

 

谁创建谁删除时是设计的一个理念。shm_server负责创建和删除。 

通过演示,我们可以看到成功试验。

 1.4通过shm完成进程间通信

 

 1.5shm的特点

①shm共享内存的优点

shm的优点是它是所有进程间通信中,速度最快的!可以大大地减少数据的拷贝次数。

为什么shm可以减少拷贝次数呢?

 上面同样的实现通信,pipe需要创建缓冲区,而shm可以不设缓冲区,直接对shm进行写入和读取,这样就减少了两次拷贝。在不考虑输入输出流的情况下,只有两次拷贝,相比于pipe的四次拷贝少了两次。

②shm的缺点

我们更改一下代码,通过演示更方便我们看出它的特点。

 发送信息变成5s发送一次,读取变成每隔1s读取一次,换句话说就是发送慢于读取。

 通过演示可以看到,server读取的信息编号都是1.

这一点和pipe大为不同,在pipe中当读取过pipe中的信息后,如果pipe没有新的消息写入,就不会读取而是等待输入端写入信息。而shm则是读取一次消息后,没有新的消息就会继续读取原来旧的消息。

所以说shm的缺点就是:

shm不对数据进行同步和互斥的操作,没有对数据做任何保护!

而我们要想避免这种现象,需要信号量或者互斥锁(多线程)

1.6shm的内核结构

①内核

通过接口shmctl()可以查看shm的内核数据结构。

我们看到内核数据结构中为什么没有key的信息呢?这是因为OS对它进行了封装:

 

我们可以验证一下是否ipc_perm结构中的__key就是我们的key呢?

 

我们看到确实就是我们初始传输的key。

 ②shm大小的问题

一般shm的大小,建议设置为4KB的整数倍。

因为系统分配shm是以4KB为单位的!---内存划分内存块的基本单位是4KB,一个4KB大小的空间,内存当中是一个Page

那么如果我们申请空间4097个字节,那么内核申请的空间大小会向上取整,申请4KB*2大小的空间。那么我们试着申请4097B大小的空间。

但是发现shm的大小好像并不像我们所说的申请了8KB的 空间,而是4097.为什么呢?

这是因为内核虽然给我们申请了8KB的空间,但是我们之申请了4097B的空间大小,所以内核只给我们提供8KB中的4097B大小的空间供我们使用。

🎞二、消息队列&&信号量

2.1消息队列

因为system V版本因为它只能在本地进程间通信的特性,渐渐不被使用了。所以只简略介绍消息队列和信号量。

 消息队列的使用模式是:写端以数据节点的方式将数据放到消息队列当中,而读端就可以从消息队列中拿走数据。而消息队列可以两端互为读写,因为是在同一个消息队列中,为了区分哪端为读哪端为写,有一个type类型,用来标识这个消息是由哪一端写入的。

比如由一端发送的数据都设为0,另一端发送的数据都设为1,这样标识数据是由哪一端发送的。

它的接口设计和shm的接口是十分相似的。

①msgget

 

 ②msgctl

 ③msgsnd

 ④msgrcv

用于读取消息队列。

 2.2信号量

信号量的概念有点抽象。它的本质是一个计数器,通常用来表示公共资源中,资源数量有多少。

首先来说明一下什么是公共资源:

 而被保护的公共资源称为临界资源。具体的保护涉及到了互斥和同步的原理。信号量用来表示公共资源中资源数量的多少,要完成进程间通信,不仅需要不同进程看到相同的公共资源,信号量本身也需要让不同的进程看到资源数量的多少。信号量也要打破进程间独立,所以它也被划分到进程间通信的范畴中!

为什么要有信号量呢?

我们平时想看电影,需要买票,买票的本质就是对放映厅中的作为进行预订。而我们想要某种资源时,也可以通过信号量预订。

①semget

 sems:申请信号量的个数。

semflg:选项IPC_CREAT 和 IPC_EXCL

 ②semctl

 semid:信号量的identifier。

semnum:信号量的下标。

我们看到IPC资源的组织方式,接口相似度非常高,尤其是获取与删除。

并且我们可以观察一下内核数据结构:

system V版本的进程间通信标准是非常统一的。其中都使用了ipc_perms的结构体来维护__key等属性信息。

那么这样做有什么好处呢?

我们可以创建一个指针数组,每一个成员都是ipc_perm结构体的地址。

 

 因为结构体的第一个成员的地址,在数字上和结构体对象本身的地址数字是相等的!换句话说我们指针数字的每一个成员都是一个system V标准的内核数据结构体的地址!只不过大小只是ipc_perm结构体的大小。但是我们可以通过强转类型,比如将perms[0]强转为struct shmid_ds*类型。就可以通过指针数组的内容强转拿到内核数据结构体的地址,这样就可以访问它的其他内容!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

78.建立一个Web应用程序的布局第二部分

上节课中&#xff0c;我们实现的页面如下图所示&#xff1a; 而最终的页面如下图所示&#xff1a; ● 首先我们 先添加menu的按钮 <menu><button>New</button><button>Reply</button><button>Forward</button><button>Mar…

中兴新支点操作系统电力主站和变电站安全操作系统解决方案

近日&#xff0c;由中国软件行业协会主办的“第二届中国国际软件发展大会”在北京国家会议中心成功召开&#xff0c;国家部委领导、两院院士、行业领袖、龙头企业代表等齐聚一堂&#xff0c;剖析行业热点、分享趋势前瞻。中兴新支点操作系统凭借在国网和南网广泛应用的出色表现…

彻底明白IP地址如何计算相关地址【收藏】

通过IP地址和子网掩码与运算计算相关地址&#xff0c;知道ip地址和子网掩码后可以算出&#xff1a; 1、 网络地址 2、 广播地址 3、 地址范围 4、 本网有几台主机 例1&#xff1a;下面例子IP地址为1921681005 子网掩码是2552552550。算出网络地址、广播地址、地址范围、主…

17种常见VR推广渠道,你知道几个?

随着各方面技术的成熟&#xff0c;VR内容越来越多地出现在了生活的各个角落&#xff0c;凭借其身临其境的3D沉浸式体验&#xff0c;惊艳了不少消费者&#xff0c;为线上平台、实体店铺导流变现实现了极大的价值&#xff0c;成为了当下商企最受欢迎的营销模式。 此前我们经常收…

TFM—用于实时监控和数据管理的远程试验管理平台

随着信息技术的高速发展&#xff0c;企业对远程试验实时监控与数据管理的需求日益增强。而利用远程试验信息协同技术&#xff0c;可突破部门与地域的限制&#xff0c;并把试验现场的车辆状态信息、试验数据和分析结果实时传输给数据分析部门和设计部门等&#xff0c;从而缩短时…

死锁知识记录

一、类型 一般性死锁&#xff1a;这是最经典的死锁方式。指的是多个线程的执行下必须拥有多个资源&#xff0c;但是这些资源又分别被不同的线程占有着&#xff0c;即造成了一种僵持的状态。 嵌套性死锁&#xff1a;指的就是锁的互相嵌套使用。上面这种情况的死锁类型&#xf…

自动化测试的简单认识

1.什么是自动化测试 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条件包括正常和异常&#xff0c;最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。 2.常见的WebDriver的API 定位元素常用的是 findelement方法 比…

MySQL 锁篇

1. MySQL 有哪些锁&#xff1f; 1&#xff09;全局锁 执行后整个数据库就处于只读状态&#xff0c;一般用于全库逻辑备份 2&#xff09;表级锁&#xff1a; 表锁&#xff1a; 表级别的共享锁&#xff1a;读锁 表级别的独占锁&#xff1a;写锁 元数据锁&#xff08;MDL&am…

一文吃透 Vue 框架教程(下)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【Spring】— MyBatis配置文件元素

目录 MyBatis配置文件元素properties元素settings元素typeAliases元素typeHandler元素objectFactory元素plugins元素environments元素mappers元素 MyBatis配置文件元素 使用MyBatis框架进行开发&#xff0c;需要创建MyBatis的核心配置文件&#xff0c;该配置文件包含重要的元素…

sqlite数据如何转成mysql数据类型

一、使用工具Navicat Premium 16 1.把db文件拖到Navicat Premium中&#xff0c;选择数据库&#xff0c;点击工具&#xff0c;数据传输 选择下一步 下一步 开始 这样就成功了&#xff0c;生成的sql文件就在你保存的位置了。 二、使用SQLiteStudio转换成mysql文件 1.打开SQLite…

关键字volatile 和信号

volatile是c语言中的一个关键字&#xff0c;在语言层面我们很难理解它&#xff0c;今天从信号角度我们来理解一下。 我们来看下面一段代码&#xff1a; 从代码表面看上去运行逻辑应该是&#xff0c;flag为0时候一直while循环&#xff0c;当有信号2产生进入到信号2的处理函数中…

Java - 集合工具类Collections

文章目录 目录 文章目录 前言 二.collections提供的方法 三. 方法详解 1.addAll:将所有指定元素添加到指定 collection 中。 可变参数 添加方式 二.shuffle()&#xff1a;随机打乱List集合中的元素 三. sort()&#xff1a;对List集合进行排序&#xff1b; 实现compata…

软件测试:提升jemeter报告输出品质,精通动态参数处理技巧并进行组件极致优化

目录 引言 一.测试报告生成 二.动态参数处理 1.正则 2.json提取器 3.JMeter动态参数处理逻辑是什么&#xff1f;【面试必考】 三.jemter常用的组件 四.JMeter是怎么做API自动化测试的&#xff1f; 五.针对一个服务&#xff0c;你怎么测试&#xff1f; 引言 当今互联网…

spring jpa/hibernate 查询缓存导致内存溢出

版本 hibernate-5.6.10 问题 应用运行一段时间后发生堆空间不足内存溢出 根据内存快照可见大量org.hibernate.engine.query.spi.QueryPlanCache对象 原因 QueryPlanCache会缓存sql&#xff0c;以便于相同的sql重复编译 如果大量使用in查询&#xff0c;由于参数数量不同&a…

《程序员面试金典(第6版)》面试题 02.02. 返回倒数第 k 个节点(双指针法,链表)

题目描述 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 题目传输门&#xff1a;添加链接描述 示例&#xff1a; 输入&#xff1a; 1->2->3->4->5 和 k 2 输出&#xff1a; 4说明&#xff1a; 给定的 k 保证是有效的。 解题思路与…

Axure教程-横向动态堆叠图(中继器)

本文将教大家如何用AXURE中的中继器动态横向堆叠图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://3ajwd3.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87810612 二、功能介绍 简单填写中继器内容即可生成动态竖向堆…

移动应用测试不可少的技能,使用Appium和Python实现Activity切换

目录 前言&#xff1a; 一、Appium简介 二、切换Activity操作 三、使用 Appium 实现切换 Activity 操作的注意事项 四、结论 前言&#xff1a; App测试自动化是当前移动应用开发测试领域中的热点之一。在应用开发的过程中&#xff0c;切换Activity是一个常见的操作&#x…

网易易盾流量多发反外挂落地实践

背景及目的 环境迁移 反外挂服务建德机房线上迁移&#xff0c;采取的方案是&#xff1a;建德机房独立部署一套完整的集群&#xff0c;统一经由完整的性能测试、故障演练、功能回归后&#xff0c;通过线上分阶段切换流量的方式来切服务。QA 需要比对验证 2 个不同环境下核心接口…

PostgreSQL技术内幕(八)源码分析 ——投影算子和表达式计算

在上期Postgres技术内幕系列直播中&#xff0c;我们为大家介绍了Postgres投影算子和表达式计算实现原理和底层细节。本文根据直播内容整理&#xff0c;作者现任HashData内核研发工程师。 投影 (projection) 关系代数中的一种&#xff0c; 用于从关系R中选出属性包含在A中的列…