【Linux详解】——共享内存
📖 前言:本期介绍共享内存。
目录
- 🕒 1. 共享内存的原理
- 🕒 2. 共享内存的概念
- 🕘 2.1 接口认识
- 🕘 2.2 演示生成key的唯一性
- 🕘 2.3 再谈key
- 🕒 3. 共享内存相关命令
- 🕒 4. 利用共享内存进行进程间通信
- 🕒 5. 共享内存的优缺点
🕒 1. 共享内存的原理
在之前学过的进程地址空间的基础上,我们知道,进程之间具有独立性,因为每个进程的内核数据结构的数据以及页表的映射都是独立的。而对于共享内存,我们同样了解,这是为了让进程之间能够进行通信的公共空间,接下来就通过进程地址空间的结构去了解共享空间的位置及原理:
OS为了让两个毫不相关的进程之间进行通信,进行了三个工作:
- 在对应的内存当中让用户帮OS申请一块空间(通过指定的调用接口)
- 将创建好的内存映射进进程的地址空间(用户就可以通过访问起始地址的方式来进行对申请的这块内存空间的访问)
- 未来不想通信:
- 取消进程和内存的映射关系
- 释放内存
因此,我们把申请的这块空间称之为共享内存,将映射关系称之为进程和共享内存进行挂接。将取消进程和内存的映射关系称之为去关联,释放内存释放的就是共享内存。
理解:
- 进程间通信,是专门设计的,用来IPC的,和malloc/new不是一个东西。
- 共享内存是一种通信方式,所有想通信的进程,都可以用。
- OS中一定会存在着很多共享内存。
🕒 2. 共享内存的概念
通过让不同的进程,看到同一个内存块的方式,叫做共享内存。
🕘 2.1 接口认识
#include<sys/ipc.h>
#include<sys/shm.h>int shmget(key_t key, size_t size, int shmflg);// size:共享内存的大小
对于shmflg
,常见的有两种选择:
IPC_CREAT
:如果不存在共享文件则创建,存在则获取IPC_EXCL
:- 无法单独使用,单独使用没有意义,需要结合
IPC_CREAT
IPC_CREAT|IPC_EXCL
:如果不存在,就创建,如果已存在,就出错返回。即在用户的角度,如果创建成功,一定是一个新的shm
!
- 无法单独使用,单独使用没有意义,需要结合
shmget返回值: 记住他是一个标识符就够用了,得到的是共享内存的标识符。(和文件fd没有任何关系)
key: 是什么不重要,最重要的是其具备的唯一性。
而获取key值,则通过一个新的接口:ftok
,ftok
通过指定的字符串数据*pathname
以及char类型的proj_id
数据进行一系列的算法整合返回了具有唯一性的Key:
key_t ftok(char *pathname, char proj_id);
由于创建的key值有可能已经被别人使用了,因此有失败的可能性。创建Key值如果失败,则返回-1。
🕘 2.2 演示生成key的唯一性
# Makefile
.PHONY:all
all:shm_client shm_servershm_client:shm_client.ccg++ -o $@ $^ -std=c++11
shm_server:shm_server.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f shm_client shm_server
// comm.hpp
#ifndef _COMM_HPP_
#define _COMM_HPP_#include<iostream>
#include<cerrno>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<sys/ipc.h>
#include<sys/shm.h>#define PATHNAME "."//当前路径
#define PROJ_ID 0x66key_t getKey()
{key_t k = ftok(PATHNAME, PROJ_ID);if(k < 0){// cin, cout, cerr ->stdin, stdout, stderr->0, 1, 2;标准错误stderr向2打印。std::cerr << errno << ":" << strerror(errno) << std::endl;exit(1);//终止进程}return k;
}#endif
// shm_server.cc
#include"comm.hpp"int main()
{key_t k = getKey();printf("0x%x\n", k);return 0;
}
// shm_client.cc
#include"comm.hpp"int main()
{key_t k = getKey();printf("0x%x\n", k);return 0;
}
[hins@VM-12-13-centos shm]$ ./shm_server
0x6601062a
[hins@VM-12-13-centos shm]$ ./shm_client
0x6601062a
通过make后执行发现,两个程序的k值是一样的,这就证明了ftok指定参数的返回值是唯一的。(k实际上就是32位的一个整数)
🕘 2.3 再谈key
OS中一定存在多个共享内存,因为彼此之间可能都需要通信,因此也就都需要申请一块空间。而OS申请的共享空间,也一定和进程一样需要被管理,既然需要管理,那么一定也是先描述再组织的方式,即共享内存 = 物理内存块+共享内存的相关属性 。
之前谈到过,key是什么不重要,能进行唯一性的标识最重要,因此创建共享内存的时候,是如何保证共享内存在系统中是唯一的呢?当然是通过key来确定的,只要一个进程也看到了同一个key,就能够访问这个共享内存。那么key在哪里,实际上这就和PCB一样,key就在内核中的属性集合里,即:
struct shm{key_t key;//...
}
即:key是通过shmget这样的系统调用,设置进入共享内存属性中,用来表示该共享内存在内核中的唯一性!
shmid和key就好比fd和inode。为什么有了key还需要shmid呢?通过key和shmid的区分,能够面向系统层面和用户层面,这样能够更好的进行解耦,以免内核中的变化影响到用户级。
🕒 3. 共享内存相关命令
通过让不同的进程,看到同一个内存块的方式,叫做共享内存。
查看共享内存:ipcs -m/-q/-s
(共享内存/消息队列/信号量数组)
删除共享内存:ipcrm -m shmnid
将共享内存与虚拟内存进行关联:
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);// 共享内存id,被映射的进程地址空间(给nullptr),给0默认可以读写。成功时,将返回共享内存的虚拟地址。失败返回-1(失败错误码errno被设置)
将共享内存与虚拟内存去关联:
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);//参数:shmat的返回值。成功时,将返回0。失败返回-1(失败错误码errno被设置)
控制(主要用移除)共享内存(shmctl):
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);//shmid(类似fd),传入系统设定的宏,shmid_ds数据结构。传入IPC_RMID移除共享内存成功时,将返回0。失败返回-1(失败错误码errno被设置)
🕒 4. 利用共享内存进行进程间通信
// comm.hpp
#pragma once
#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define PATHNAME "."//当前路径(路径都行)
#define PROJ_ID 0X55//项目id也无要求
#define MAX_SIZE 4096
key_t getKey()
{key_t k=ftok(PATHNAME, PROJ_ID);if(k==-1){std::cout<<"ftok"<<errno<<":"<<strerror(errno)<<std::endl;exit(1);}return k;
}
int getShmHelper(key_t key,int flags)
{int shmid=shmget(key,MAX_SIZE,flags);if(shmid==-1)//创建共享内存失败{std::cerr<<"shmget"<<errno<<":"<<strerror(errno)<<std::endl;exit(2);}return shmid;//返回共享内存标识符
}
int getShm(key_t key)//创建||获取共享内存
{return getShmHelper(key,IPC_CREAT);//传0也行
}
int createShm(key_t key)//必定创建共享内存
{return getShmHelper(key,IPC_CREAT|IPC_EXCL|0600);//生成一个全新的共享内存
}
void* attachShm(int shmid)//让共享内存与虚拟内存建立联系
{void* memstart=shmat(shmid,nullptr,0);if((long long)memstart==-1L){std::cerr<<"shmat"<<errno<<":"<<strerror<<std::endl;exit(3);}return memstart;
}
void detchShm(void* memStart)//去关联
{if(shmdt(memStart)==-1){std::cerr<<"shmdt"<<errno<<":"<<strerror<<std::endl;exit(4);}
}
void delShm(int shmid)//删除共享内存
{if(shmctl(shmid,IPC_RMID,nullptr)==-1){std::cerr<<"shmctl"<<errno<<":"<<strerror<<std::endl;}
}
// shm_server.cc
#include "comm.hpp"
int main()
{key_t k=getKey();printf("0X%x\n",k);int shmid=createShm(k);char* memStart=(char*)attachShm(shmid);//让共享内存与虚拟内存建立联系printf("memStart address:%p\n",memStart); //通信接收代码while(true){printf("client say:%s\n",memStart); sleep(1);//调用用户级结构体struct shmid_ds ds;//创建结构体对象dsshmctl(shmid,IPC_STAT,&ds);//获取ds对象的状态printf("获取属性:%d,pid:%d,myself:%d,key:%d\n",ds.shm_segsz,getpid(),ds.shm_cpid,ds.shm_perm.__key);}detchShm(memStart);//去关联sleep(10);delShm(shmid);//删除共享内存,client和server都能删除共享内存,尽量谁创建谁删return 0;
}
// shm_client.cc
#include "comm.hpp"
int main()
{key_t k=getKey();printf("0X%x\n",k);int shmid=getShm(k);//获取共享内存sleep(5);char* memStart=(char*)attachShm(shmid);//让共享内存与虚拟内存建立联系printf("memStart address:%p\n",memStart); //通信传输代码const char* massage="I am client";pid_t id=getpid();int cnt=0;//发送计数while(true){snprintf(memStart,MAX_SIZE,"%s[%d]:%d\n",massage,getpid,++cnt);sleep(1);}detchShm(memStart);//去关联return 0;
}
🕒 5. 共享内存的优缺点
优点:共享内存是所有进程间通信中速度最快的。(无需缓冲区,能大大减少通信数据的拷贝次数)
缺点:如果服务端读取速度较快,用户端发送数据较慢,就会产生同一段消息被服务端读取多遍。共享内存是不进行同步和互斥的,没有对数据进行任何保护。
共享内存大小的建议:因为系统分配共享内存是以4KB为基本单位,一般建议申请共享内存的大小为4KB的整数倍。
OK,以上就是本期知识点“共享内存”的知识啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉如果觉得收获满满,可以点点赞👍支持一下哟~
❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页
相关文章:

【Linux详解】——共享内存
📖 前言:本期介绍共享内存。 目录 🕒 1. 共享内存的原理🕒 2. 共享内存的概念🕘 2.1 接口认识🕘 2.2 演示生成key的唯一性🕘 2.3 再谈key 🕒 3. 共享内存相关命令🕒 4. 利…...
Golang 几个不错的实用函数库
文章目录 samber/lothoas/go-funkduke-git/lancetelliotchance/piegookit/goutildablelv/cyan 大咖好呀,我是恋喵大鲤鱼。 Golang 标准库是 Go 语言自带的一组核心功能库,功能全面,易于使用。 在 Golang 标准库的基础上,还可以进…...

【Linux】地址空间概念
目录 前言: 地址空间回顾 验证:一个变量是否会有两个值? 一. 什么是地址空间 虚拟地址与物理地址之间的关系 二. 地址空间是如何设计的 1. 回答一个变量两个值 2.扩展 继续深入理解 三. 为什么要有地址空间 原因: 1. 使…...

视频集中存储/直播点播平台EasyDSS点播文件分类功能新升级
视频推拉流EasyDSS视频直播点播平台,集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 TSINGSEE青犀视频的EasyDSS平台具有点播文件分类展示方法…...

JavaScript基础06——let和var两个关键字有啥不同
哈喽,小伙伴们大家好,我是雷工! 每日学习一点点,今天继续学习JavaScript基础知识,下面是学习笔记。 1、变量的本质 内存:计算机中存储数据的地方,相当于一空间。 变量的本质:是程序…...
Apache Doris 2.0.1 1.2.7 版本正式发布!
亲爱的社区小伙伴们,我们很高兴的宣布,2023 年 9 月 4 日 我们正式发布了 Apache Doris 2.0.1 和 Apache Doris 1.2.7 这两个版本,这两个版本由上百名位贡献者共同努力完成的,提供了更多有用的新特性,同时修复了若干已…...

YOLOv5算法改进(11)— 替换主干网络之EfficientNetv2
前言:Hello大家好,我是小哥谈。EfficientNetV2是一个网络模型,旨在提供更小的模型和更快的训练速度。它是EfficientNetV1的改进版本。EfficientNetV2通过使用更小的模型参数和采用一种称为Progressive Learning的渐进学习策略来实现这一目标。…...
Lombok讲解
Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,如:getter、setter、equals、hashCode、toString等。 Lombok的常用注解有: Data:这是一个自定义注解,它相当于Getter…...
【Android】功能丰富的dumpsys activity
在Android中,要查看客户端Binder的连接数,可以通过dumpsys命令结合service参数来获取相关信息。请按照以下步骤进行操作: 连接到设备的计算机上,打开命令行终端。 使用adb shell命令进入设备的Shell环境。 执行以下命令来查看服…...

亚马逊云科技 云技能孵化营——我的云技能之旅
文章目录 每日一句正能量前言活动流程后记 每日一句正能量 不能在已经获得足够多的成功时,还对自己的能力保持怀疑,露出自信的微笑,走出自信的步伐,做一个自信的人! 前言 亚马逊云科技 (Amazon Web Services) 是全球云…...
南大通用数据库-Gbase-8a-学习-38-常规日志(general log)
目录 一、环境信息 二、general log的用途 三、general log相关参数介绍 四、LInux环境模拟实验 1、查看参数配置 2、开启general log 3、输入测试SQL 4、查看文件级别general log 5、改为表级别general log 6、再次输入测试SQL 7、查看gbase.general_log 一、环境信…...
汽车信息安全导图
尊敬的读者们,欢迎来到我的信息安全专栏。在这个专栏中,我将结合我在信息安全领域的开发经验,为大家深入浅出地讲解信息安全的重要性和相关知识点。 在数字化时代,信息成为了我们生活中不可或缺的一部分。我们的个人信息、交易数据、社交网络、公司机密等都以电子形式存储…...
【元宇宙】区块链,元宇宙最大化的驱动力
如今,一些观察者认为区块链是在结构上实现元宇宙的必要条件,而其他人则认为这种说法是荒谬的。人们对于区块链技术本身仍然有很多困惑,所以根本谈不上清楚地了解込块链技术与元宇宙的关系。所以,我们可以从区块链的定义开始介绍。…...

$ref属性的介绍与使用
在Vue.js中,$ref是一个特殊的属性,用于访问Vue组件中的DOM元素或子组件实例。它允许你直接访问组件内部的DOM元素或子组件,并且可以在需要时进行操作或修改。以下是有关$ref的详细介绍和示例演示,给大家做一个简单的介绍和概念区分…...
Holistic Evaluation of Language Models
本文是LLM系列文章,针对《Holistic Evaluation of Language Models》的翻译。 语言模型的整体评价 摘要1 引言2 前言3 核心场景4 一般指标5 有针对性的评估6 模型7 通过提示进行调整8 实验和结果9 相关工作和讨论10 缺失11 不足和未来工作12 结论 摘要 语言模型&a…...
android 布局 横屏 android横屏适配
一、刘海屏适配 1、layoutInDisplayCutoutMode属性 Android 9.0系统中提供了3种layoutInDisplayCutoutMode属性来允许应用自主决定该如何对刘海屏设备进行适配。 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 这是一种默认的属性,在不进行明确指定的情况下,系…...

北京已收录2023开学了《乡村振兴战略下传统村落文化旅游设计》中国建筑出版传媒许少辉八一新书
北京已收录2023开学了《乡村振兴战略下传统村落文化旅游设计》中国建筑出版传媒许少辉八一新书...

【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】
【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】 文章目录 【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】一、安装Anaconda虚拟环境管理器二、创建虚拟环境并激活三、安装Pytorch四、测试pytorchReference 一、安装Anaconda虚拟环境管理器 首先进入…...
11 Python的正则表达式
概述 在上一节,我们介绍了Python的文件操作,包括:打开文件、读取文件、写入文件、关闭文件、文件指针移动、获取目录列表等内容。在这一节中,我们将介绍Python的正则表达式。正则表达式是一种强大的工具,用于在文本中进…...

关于工信部发布的app备案以及小程序备案流程
一、相关政策 通知:https://beian.miit.gov.cn/#/Integrated/lawStatute 腾讯备案:网站备案 首次备案-网站备案-文档中心-腾讯云 阿里备案:网站备案_ICP备案_备案迁移_备案-阿里云 二、遇到的问题 APP备案 安卓获取平台公钥方法…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...