【Linux初阶】system V - 共享内存

news2024/12/25 9:05:13

文章目录

  • 前言
  • 一、共享内存初识
    • 1.共享内存的原理
    • 2.理解共享内存
    • 3.共享的内存的概念
  • 二、共享内存函数
    • 1.shmget函数
    • 2.shmat函数
    • 3.shmdt函数
    • 4.shmctl函数
  • 三、共享内存的查看方法及其特征
  • 四、共享内存的代码实现
  • 五、共享内存优缺点分析
    • 1.共享内存的优点
    • 2.共享内存的缺点
  • 六、共享内存内核数据结构理解
  • 结语


前言

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


一、共享内存初识

1.共享内存的原理

在物理内存中申请一块空间,将创建好的内存映射进进程的地址空间中,然后将地址空间这块区域的起始地址返回给上层用户,用户最终可以通过访问起始地址的方式实现对内存的访问。

照猫画虎,同样的一块内存空间可以映射进另一个进程的地址空间中,返回起始地址给用户,另一个进程的上层用户也可以实现的同一块内存的访问,最终实现进程间通信。

未来不想通信:a.取消进程和内存的映射关系; b.释放内存。

在这里插入图片描述

这一块被进程共享的内存称为 共享内存。将创建好的进程映射进进程的地址空间,我们称这个步骤为进程和共享内存挂接。而取消进程与共享内存的映射我们称之为 去关联

———— 我是一条知识分割线 ————

2.理解共享内存

  1. system V - 共享内存版本的进程间通信,是专门设计的,用于IPC(进程间通信)。
  2. 共享内存是一种通信方式,所有想通信的进程,都可以使用。
  3. OS中一定会同时存在很多的共享内存。

3.共享的内存的概念

通过让不同进程,看到同一个内存块的方式,我们就称之为:共享内存


二、共享内存函数

常识补充:shm - 共享内存

1.shmget函数

功能:用来创建共享内存
原型
 int shmget(key_t key, size_t size, int shmflg);
参数
 key:这个共享内存段名字
 size:共享内存大小
 shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
  • key能进行共享内存的唯一性标识,它是由 ftok() 函数得来的。
  • shmflg常见参数有两个:IPC_CREAT、IPC_EXCL。
  • IPC_CREAT- 如果不存在,创建之,如果存在,获取之。
  • IPC_EXC - 无法单独使用,使用方法: IPC_CREAT | IPC_EXC, 如果不存在,创建之,如果存在,就返回出错(说明:如果创建成功,一定是新的ssh)

共享内存 = 物理内存块 + 共享内存的相关属性,我们在申请共享内存的时候,也要对共享内存做管理,管理方法:将共享内存的属性对象用数据结构(struct shmid_ds)的方式管理起来

注意:key的信息会被 shmget函数设置进共享内存的属性对象中保存起来

2.shmat函数

功能:将共享内存段连接到进程地址空间
原型
 void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
 shmid: 共享内存标识
 shmaddr:指定连接的地址
 shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1
  • 说明
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - 
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

3.shmdt函数

功能:将共享内存段与当前进程脱离
原型
 int shmdt(const void *shmaddr);
参数
 shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

4.shmctl函数

功能:用于控制共享内存
原型
 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
 shmid:由shmget返回的共享内存标识码
 cmd:将要采取的动作(有三个可取值)
 buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1
  • cmd的三个可取值

在这里插入图片描述


三、共享内存的查看方法及其特征

  • 共享内存的命令行式查看方法
ipcs -m		#查看被用户使用的共享内存
ipcrm -m shmip	  #删除特定shmip的共享内存

共享内存的特征:共享内存的生命周期是跟随OS的,不是跟随进程的。也就是说,我们需要在指令行下对自己创建的用户级共享内存进行手动删除


四、共享内存的代码实现


五、共享内存优缺点分析

1.共享内存的优点

优点:在所有进程间通信的方法中,共享内存的速度是最快的

如果使用管道,用户拷贝 6次,键盘的输入数据 -> 语言级缓冲区 -> 进程对应的文件缓冲区 -> 管道 -> 另一个进程对应的文件缓冲区 -> 语言级缓冲区 -> 屏幕。

如果使用共享内存,用户拷贝 4次,键盘的输入数据 -> 语言级缓冲区 -> 共享内存 -> 语言级缓冲区 -> 屏幕。

我们知道,在企业的数据通信中,数据往往非常庞大,此时使用共享内存可以大大降低拷贝次数

2.共享内存的缺点

缺点:共享内存不会给我们进行同步和互斥操作,没有对我们的数据做任何保护

也就是说,共享内存没有对写端在写、读端不读,写端不写、读端一直读,共享内存数据已满等情况,做相应的阻塞或其他保护。

通常情况下,工程师们会对共享内存进行一定的封装,实现对共享内存的保护。


六、共享内存内核数据结构理解

下面是共享内存暴露给用户的用户级数据结构:

struct shmid_ds {
 struct ipc_perm shm_perm; /* operation perms */
 int shm_segsz; /* size of segment (bytes) */
 __kernel_time_t shm_atime; /* last attach time */
 __kernel_time_t shm_dtime; /* last detach time */
 __kernel_time_t shm_ctime; /* last change time */
 __kernel_ipc_pid_t shm_cpid; /* pid of creator */
 __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
 unsigned short shm_nattch; /* no. of current attaches */
 unsigned short shm_unused; /* compatibility */
 void *shm_unused2; /* ditto - used by DIPC */
 void *shm_unused3; /* unused */
};

在上文中我们就曾学习过,在内核层面上,为了帮助不同的进程能找到同一块共享内存,我们有 key存在于共享内存的数据结构对象中,它可以让不同进程确定是否看到的是同一块共享内存

此时问题来了,为什么我没有在你的数据结构中找到 key的信息呢?事实上,我们看不到 key,是因为设计者对其做了相应的封装,它就被保存在了下面这个结构体中:

 struct ipc_perm shm_perm; /* operation perms */

在这里插入图片描述

程序获取共享内存部分数据结构展示:

	printf("获取属性: size: %d, pid: %d, myself: %d, key: 0x%x", \
            ds.shm_segsz, ds.shm_cpid, getpid(), ds.shm_perm.__key);

输出结果如下:

在这里插入图片描述


结语

🌹🌹 system V - 共享内存 的知识大概就讲到这里啦,博主后续会继续更新更多C++ 和 Linux的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

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

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

相关文章

uni-app弹窗列表滚动, 弹框下面的内容也跟随滚动解决方案

滑动弹窗里的列表,弹框下面的内容也会跟着滑动,导致弹窗中的列表不能正常滚动 1.弹窗组件代码,需要在最外层的view中加入touchmove.stop.prevent"moveHandle",且弹窗中需要滚动的列表要使用scroll-view标签包裹起来&…

学生课堂行为识别教学质量评估 yolov7

学生课堂行为识别教学质量评估系统利用教室安装的摄像头,学生课堂行为识别教学质量评估系统对学生的表情状态、课堂表现和互动行为进行全面监测。对学生的参与度、专注度、互动质量等进行评估,为教师提供有关教学效果的实时反馈。可以为教师提供个性化的…

深谙封装之道:requests再封装,更完美的请求函数

这集我们来讲一个requests的封装函数。 作为一个程序员,我们经常会追求代码的复用性,所以就很多三方库,让我们不重复造轮子。但三方库也不是一步到位的,真正要完成目标还是要动动手的,把工具组装起来。相信每个人都封…

win10在vmware15中安装macos10.13系统

第一步、安装vmware版本信息如下 第二步、下载unlocker-main和darwin.iso放到安装文件夹 第三步、管理员身份运行win-install.cmd 第四步、运行vmware新建虚拟机 第五步、启动新创建的虚拟机macOS 10.13并选择语言 第六步、选择磁盘工具抹掉磁盘 第七步、格式化完成后退出磁盘工…

dialogbot:开箱即用的对话机器人解决方案,涵盖问答型对话、任务型对话和聊天型对话等多种场景,为您提供全方位的对话交互体验。

dialogbot:开箱即用的对话机器人解决方案,涵盖问答型对话、任务型对话和聊天型对话等多种场景,支持网络检索问答、领域知识问答、任务引导问答和闲聊问答,为您提供全方位的对话交互体验。 人机对话系统一直是AI的重要方向&#xf…

二叉搜索树K和KV结构模拟

一 什么是二叉搜索树 这个的结构特性非常重要,是后面函数实现的结构基础,二叉搜索树的特性是每个根节点都比自己的左树任一节点大,比自己的右树任一节点小。 例如这个图, 41是根节点,要比左树大,比右树小&…

数据结构-队列的实现(C语言版)

前言 队列是一种特殊的线性表,它只允许在一端对数据进行插入操作,在另一端对数据进行删除操作的特殊线性表,队列具有先进先出的(FIFO)的 特性,进行插入操作的一端称为队尾,进行删除操作的一端称…

关于Android Studio Http Proxy设置

对敌人最大的蔑视就是沉默。--鹿丸 我们使用Android Studio 开始构建的时候会有卡顿的情况,甚至死机,也就是所谓的【android studio】构建卡住问题,如果依赖库类都是国内的,检查是否开启了代理 这个地方选择下面的自动代理 国内…

Redis_事务操作

13. redis事务操作 13.1事务简介 原子性(Atomicity) 一致性(Consistency) 隔离性(isolation) 持久性(durabiliby) ACID 13.2 Redis事务 提供了multi、exec命令来完成 第一步,客户端使用multi命令显式地开启事务第二步,客户端把事务中要执行的指令发…

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果iOS

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果 在WebRTC音视频通话的GPUImage美颜效果图如下 可以看下 之前搭建ossrs服务,可以查看:https://blog.csdn.net/gloryFlow/article/details/132257196 之前实现iOS端调用ossrs音视频通话,可以查…

KNN分类器、神经网络原理基础与代码实现

急切学习 两步:(1)归纳 (2)演绎 例如:贝叶斯分类器、决策树分类等等。 惰性学习 将训练数据建模过程推迟到需要对样本分类时(直观理解:死记硬背,记住所有的训练数据&…

Springboot集成ip2region离线IP地名映射-修订版

title: Springboot集成ip2region离线IP地名映射 date: 2020-12-16 11:15:34 categories: springboot description: Springboot集成ip2region离线IP地名映射 1. 背景2. 集成 2.1. 步骤2.2. 样例2.3. 响应实例DataBlock2.4. 响应实例RegionAddress 3. 打开浏览器4. 源码地址&…

HTML表单标签大全并附有详细代码+案例

个人名片: 🐼作者简介:一名大二在校生 🐻‍❄️个人主页:落798. 🐼个人WeChat:落798. 🕊️系列专栏:零基础学java ----- 重识c语言 ---- 计算机网络—【Spring技术内幕】…

YOLOv8目标检测算法

YOLOv8目标检测算法相较于前几代YOLO系列算法具有如下的几点优势: 更友好的安装/运行方式速度更快、准确率更高新的backbone,将YOLOv5中的C3更换为C2FYOLO系列第一次尝试使用anchor-free新的损失函数 YOLOv8简介 YOLOv8 是 Ultralytics 公司继 YOLOv5…

Android学习之路(2) 设置视图

一、设置视图宽高 ​ 在Android开发中,可以使用LayoutParams类来设置视图(View)的宽度和高度。LayoutParams是一个用于布局的参数类,用于指定视图在父容器中的位置和大小。 ​ 下面是设置视图宽度和高度的示例代码: …

【算法——双指针】LeetCode 283 移动零

题目描述: 思路: (双指针) O(n)O(n)O(n) 给定一个数组 nums,要求我们将所有的 0 移动到数组的末尾,同时保持非零元素的相对顺序。 如图所示,数组nums [0,1,0,3,12],移动完成后变成nums [1,3,12,0,0] &am…

【探索SpringCloud】服务发现-Nacos使用

前言 在聊服务注册中心时,便提到了Nacos。这次便来认识一下。当然,这自然没有官方介绍那般详尽,权当是学习了解Nacos原理的一个过程吧。 Nacos简介 Nacos,全名:dynamic Naming And Configuration Service. 而这个名…

静态网页和动态网页区别

1,静态网页和动态网页有何区别 1) 更新和维护 静态网页内容一经发布到网站服务器上,无论是否有用户访问,这些网页内容都是保存在网站服务器上的。如果要修改网页的内容,就必须修改其源文件,然后重新上传到服务器上。…

SpringBoot框架

一、SpringBoot概述 1. 简介 springboot是spring家族中的一个全新框架,用来简化spring程序的创建和开发过程。在以往我们通过SpringMVCSpringMybatis框架进行开发的时候,我们需要配置web.xml,spring配置,mybatis配置,…

【算法训练营】队列合集(2) 2073. 买票需要的时间 || 面试题 03.04. 化栈为队 ||

📍前言 本篇将学习queue的OJ题,每一题的标题都是超链接哦,我会将queue的基础知识放到最后供你参考~ 🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:&am…