IPC<进程间通信>之共享内存-源代码在结尾处

news2024/9/23 23:22:14

一,什么是共享内存

共享内存是进程间通信的一种方式,相较于传统的管道和命名文件的通信方式,shared memory是最快的一种方式,但是他也有一定的缺陷,下面再谈。

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

二,共享内存通信的原理 

我们要想实现不同的进程之间相互通信,第一步就一定要先让不同的进程看到同一份资源,在使用共享内存的时候,存在于内核内存中的共享内存就是这份资源。

第一步:

创建共享内存

要让不同的进程看到同一份资源的前提是,我们要先让这份资源存在。可以通过调用系统调用接口开创建共享内存。

接口函数我们先不介绍,原理讲完之后,在用代码实现的时候,我们会对原理进行复盘,到时候具体细节再说。

现在假设共享内存我们已经在内存中开辟好了,如下图所示:

第二步:

让多个进程(这里我们就以两个进程为例来谈具体的细节) 与这个共享内存建立链接,也就是让共享内存的物理地址映射到该进程的进程地址空间上去。具体一点说是,映射到进程地址空间的共享区。如下图所示:

第三步:

上述建立完链接之后,两个进程就能看到同一份资源了,各自通过对应的地址就能够完成向共享内存中写入或读取数据了。这个过程就是双方进行通信的过程,在下述的代码中会有更好的体现。

第四步:

断开链接+释放共享内存

断开链接和释放共享内存,是两个步骤,将它们放在一起合成第四点就是为了体现一点,释放共享内存之前一定要先让链接该空间的进程与其断连。

三,代码

代码的讲解大部分使用注释的方式,这样更能让大家清晰的看到创建共享内存的整个过程。

一,创建共享内存

要创建共享内存的话,我们先来认识一下shmget()函数。

shmget有三个参数,先讲第二个参数size:表示的是要创建的共享内存的大小。

第三个参数有多个选项,但是我们只需要认识下面两个就行:

 

1.单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回

2.IPC_EXCL不能单独使用,一般都要配合IPC_CREAT

3.IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 -- 如果创建成功,对应的shm,一定是最新的!

返回值:

成功返回的是共享内存的标识符

失败-1被返回。

第一个参数我们需要单独使用一个函数来获取。

ftok()的 两个参数分别是项目的路径名和项目的id,如何使用在代码中有体现,这里解释一下,为什么要使用这个函数来获取第一个参数。

如果共享内存创建成功之后,该共享内存的标识符就会被返回,但是在OS中存在着许多的共享内存,我们需要区分去该共享内存是我们创建的还是OS的,所以就需要一个方式来创建一个唯一的共享内存,ftok函数会根据你给出的项目名和项目id来为你生成一个整数,该整数具有唯一性 ,根据这个整数就能够创建一个唯一的共享内存使用,从而保证不会与其他的共享内存冲突使用。

 了解完了之后,我们就开始实现第一步的代码。

创建两个文件,代表两个进程,让其中一个进程进行写,另一个进行读取。

server.cc进行读取

 

client.cc进行写入操作。

二,建立链接

建立链接时,我们任然需要借助一个函数-shmat

其中第一个参数就是我们使用shmget()的返回值,也就是共享内存的标识。

第二个和第三个参数并不需要了解的太深入,感兴趣的话可以查一下网上的很多文章,这里我们直接将这两个参数分别设置成nulllptr和0即可。

该函数的返回值就是共享内存的起始地址。

代码:

 

 

 三,开始通信

通信的控制就比较的自由了,这里就让client向共享内存中写一些数据,如何让server去读取数据并打印出来。

代码如下:

 

编译完成之后,我们让server先运行起来,创建一个共享内存,如何再运行起client,观察结果:

 

可以很好的看到,在我们的没有运行cilent的时候,server一直在等待,当我们运行起client的时候,共享内存中被写入数据,server读取了该数据并进行了打印。

这时一切都是正常的,可是当我们删除可执行文件之后,再重新编译,想运行可执行文件的时候,就会发生下面的报错信息:

原因就是我们上面所说的,我们在完成通信之后并没有将两个进程与共享内存进行去关联,也没有删除这个共享内存,所以我们就看到了报错:这个文件已经存在。

解法1:使用命令查看该共享内存的shmid,根据这个shmid进行删除:

 

还可以使用函数进行删除。该函数就是shmctl() 

第二个和第三个参数这里任然不过多的介绍,分别设置为IPC_RMID和nullptr 。

四,去关联

在删除的时候,因为我们是server创建的该共享内存,所以我们只需要让server进行删除即可,在删除之前让两个进程进行去关联。

去关联要使用的函数是shmdt()

它的使用也很简单,参数就是共享内存的起始地址,也就是shmat()的返回值。

代码如下:

 

接下来再进行一下测试,看一下是否还会存在上述出现的问题:

 

我们让server进程过6秒之后,自动的退出,退出之后再查看一下共享内存是否被自动删除。

所以我们将代码进行一些修改:

实验结果: 

 

 可以看到再进程server退出的时候,共享内存也被自动删除了。

总结:

在搞懂共享内存通信的原理之后,我们主要就是需要掌握一些相关函数的使用,使用共享内存进行通信我们发现也不是很难,只不过函数相对于其他的通信方式有点小多。所以认识这些函数和熟练的使用就我们需要做大量的练习。

源代码:

共享内存博客素材 · 0495797 · wxk/mylinux - Gitee.com

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

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

相关文章

从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)

目录 0. 引入6个默认成员函数 1. 构造函数(默认成员函数) 1.1 构造函数的概念 1.2 构造函数的特性和用法 1.3 默认构造函数 2. 析构函数(默认成员函数) 2.1 析构函数概念 2.2 析构函数特性 3. 拷贝构造函数(默认成员函…

附录2-购物车案例

目录 1 效果 2 接口数据 3 App.vue 4 HEADER.vue 5 COUNT.vue 6 GOODS.vue 7 FOOTER.vue 1 效果 由四种子组件和一个App.vue构成 2 接口数据 返回结果如下 {"status": 200,"message": "获取购物车列表数据成功!",&q…

idea中的debug操作详解

行断点 默认模式 方法断点 菱形,加在方法前,用的比较多的地方:加在接口前会进入这个接口的实现类。 异常断点 如果说你的程序抛了某个异常,你需要知道在哪里抛出的,可以直接设置异常断点,设置后程序会…

Shell脚本之循环语句(for、while、until)

目录 一、echo命令二 for循环语句三 while循环语句结构(迭代)四. until 循环语句结构五.continue和break和exit 一、echo命令 ?echo -n 表示不换行输出 echo -e 输出转义字符,将转义后的内容输出到屏幕上 常见转义字符: 二 for循环语句 用法…

Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置自动亮度调整BrightnessAuto(自动曝光自动增益)(C++)

自动亮度调整项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外&#xff0…

北斗哨兵北斗短报文远程监控系统解决方案

一、项目背景 随着社会发展各行各业都会遇到各种各样的安全问题,监控系统作为安防的第一线安防设备也已广泛部署,然而地处偏僻的监控区域往往面临着难以提供电力供应以及网络供应的问题,类似于山区环境监测,工地监测等复杂的环境布…

Web自动化测试流程:从入门到精通,帮你成为测试专家

B站首推!2023最详细自动化测试合集,小白皆可掌握,让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 摘要: 步骤一:选取测试工具 步骤二:编写测试用例 步骤三:编…

5月4号软件资讯更新合集.....

🚀 Layui 2.8.2 发布 更新日志 table 修复 autoSort: true 时,更改 table.cache 未同步到 data 属性的问题 修复 多级表头存在 hide 表头属性时,执行完整重载可能出现的错位问题 修复 未开启 page 属性时底边框缺失问题 优化 打印内容中…

大型游戏剧本杀小程序app

大型游戏剧本杀小程序的发展趋势主要表现为以下几个方面: 社交互动:未来大型游戏剧本杀小程序将会更加注重社交互动,为用户提供更多的沟通方式和社交场景,以增强玩家间的互动和参与感。 智能化和AR/VR技术应用&#xff1a…

网络基础项目——全网互通实验

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 前言 本章将会讲解网络基础项目——全网互通实验。 一.实验项目图 二.实验要求 1.全网互通,所有PC机能访问服务器(ping)2.路由器…

DA-Net:用于视网膜血管分割的双分支Transformer和自适应条带上采样

文章目录 DA-Net: Dual Branch Transformer and Adaptive Strip Upsampling for Retinal Vessels Segmentation摘要本文方法整体框架Transformer LayerAdaptive Strip Upsampling Block 实验结果消融实验 DA-Net: Dual Branch Transformer and Adaptive Strip Upsampling for R…

【Python习题集6】类与对象

类与对象 一、实验内容二、实验总结 一、实验内容 1.设计一个Circle类来表示圆,这个类包含圆的半径以及求面积和周长的函数。在使用这个类创建半径为1~10的圆,并计算出相应的面积和周长。 半径为1的圆,面积: 3.14 周长: 6.28 半径为2的圆&am…

【虹科案例】虹科任意波形发生器板卡在声场模拟实验中的应用

声场模拟实验介绍 声场模拟实验是一种通过模拟不同环境下的声场特征来模拟真实世界中声音传输情况的实验方法。通过模拟不同环境下的声场特征,如空间分布、强度、频率等,来模拟真实世界中的声音传输情况,从而对声学相关问题进行研究。 在声…

Java集合框架知识总结

前言 Java集合框架主要由两个接口及其下面的实现类构成,这两个接口分别是Map接口和Collection接口,下面先通过其对应的UML类图看下这两个接口的具体实现,如下 1、Map接口 Map接口的主要实现有我们熟悉的HashMap、HashTable以及TreeMap、Con…

信息技术发展

OSI网络标准协议 物理层:联网的媒介 RS232 FDDI 数据链路层: 网络层接收到的数据分割成可被物理层传输的帧 IEEE802.3/.2 ATM 网络层:网络地址翻译成对应的物理地址,路由 IP ICMP IGMP IPX ARP 传输层:端到端的错误恢复和流量控制…

轻松提升投标技术分?smardaten高性价比原型服务受热捧

日前,某个交通领域的软件公司A遇到了难题,十多个在跟的项目需要在一个月内完成投标准备工作。 应用软件“强甲方需求”的大环境下,A公司又陷“投标高峰期”。 更具挑战性的是,其中,有5个项目要求应标企业提供真实系统的…

一文介绍Linux EAS

能量感知调度(Energy Aware Scheduling,简称EAS)是目前Android手机中Linux线程调度器的基础功能,它使调度器能预测其决策对CPU能耗的影响。依靠CPU的能量模型(Energy Model,简称EM),…

steam搬砖,适合个人操作的创业项目

这个项目主就是在Steam平台买进CSGO道具,再放到网易buff平台卖出。因为进价低出价高,所以每卖出一件道具,利润都相当可观。 关键这玩意背靠Steam这个超大平台,日活几千万,几乎覆盖了市面上的所有热门游戏,…

动态规划——逆序对

逆序对Time Limit: 1000 MSMemory Limit: 5000 KB Description 给定一个长度为N的int型数组a[0,1,2,...N-1], 请计算逆序对个数.当i<j且a[i]>a[j], 则称a[i]与a[j]是一对逆序对.Input 第一行输入M表示包含M组测试数据&#xff0c;每组先输入N (N<50000), 接着输入N…

ios app真机测试到上架App Store详细教程-必看

​转载&#xff1a;https://blog.csdn.net/p312011150/article/details/89374401 ios app真机测试到上架App Store详细教程-必看 Appuploader常见问题 转存失败 重新上传 取消 上架基本需求资料 1、苹果开发者账号&#xff08;如还没账号先申请-苹果开发者账号申请教程&…