当前位置: 首页 > news >正文

Linux -- 共享内存(1)

目录

共享内存

共享内存相关函数

ftok 函数 -- 获取 key 值

什么是 key?

 如何生成 key ?

参数:

返回值:

封装:

shmget 函数 -- 获取 shmid 值

什么是 shmid? 

shmid 和 key 的区别?

如何获取 shmid ?

参数:

返回值:

封装:

shmctl 函数 -- 控制共享内存

参数:

返回值:

封装:

删除共享内存:

获得共享内存的状态:

shmat 函数 -- 将共享内存挂接到进程地址空间

参数:

返回值:

封装:

shmdt 函数 -- 取消挂接

参数:

返回值:

封装:


共享内存

共享内存是一种在计算机系统中允许多个进程访问同一块内存区域的机制。它是进程间通信(IPC, Inter-Process Communication)的一种方式,可以让不同的进程通过读写同一个内存段来交换数据。这种方式非常高效,因为它避免了数据复制的过程,直接在内存中进行数据的传递。

在操作系统层面,当一个进程创建了一个共享内存区后,其他被授权的进程可以映射这个共享内存到自己的地址空间,并且可以像访问普通内存一样访问这块共享内存。这种机制对于需要频繁交换大量数据的应用程序特别有用,比如数据库管理系统、多媒体应用程序等。

共享内存相关函数

ftok 函数 -- 获取 key 值

什么是 key?

因为两个进程访问同一块共享内存,而且操作系统不止一块共享内存,怎么保证两个或者不同的进程看到的是同一块共享内存呢?操作系统如何管理所有的共享内存?

我们给共享内存提供内核中的唯一性的标识,称为 key ,主要用于创建或访问共享内存段时标识这个内存段

 如何生成 key ?

#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);
参数:

pathname:指向一个字符串的指针,该字符串包含了一个路径名。这个路径名可以是任何文件或目录的路径,甚至可以是一个不存在的文件路径。其主要目的是为了生成一个唯一的键值。

proj_id一个整数,用于进一步区分不同的共享内存段或信号量集。proj_id通常是一个较小的整数,因为 ftok函数返回的 key 值是由路径名和 proj_id组合计算得出的。过大的 proj_id可能会影响到 key 值的分布

这个值通常由程序员根据应用程序的需要自行选择。通常情况下,开发者会根据项目的实际需求来选择一个合适的 proj_id。例如,可以使用一个固定的数字,或者是某种有意义的编码,只要保证它是唯一且一致的即可。

返回值:
  • 如果成功ftok函数返回一个非负的键值key_t类型)。
  • 如果失败返回 -1,并且会设置 errno来表明错误的原因。

封装:

key_t GetShmKeyOrDie(const char* pathname,const int pro_jid)
{key_t k=ftok(pathname,pro_jid);//得到key值if(k<0)//获取失败{cerr<<" ftok failed,errno:"<<errno<<", errstring:"<<strerror(errno)<<endl;exit(1);//直接终止程序}return k;//获取成功
}

shmget 函数 -- 获取 shmid 值

什么是 shmid? 

shmid是一个整数,用于标识一个已创建的共享内存段。一旦获取了shmid,进程就可以通过它来进一步操作共享内存段(如附着、分离等)。类似于文件描述符

shmid 和 key 的区别?

  • key用于标识共享内存段的逻辑键值,而shmid则是操作系统分配给这个共享内存段的一个内部标识符,用来管理具体共享内存段。两者共同作用于共享内存机制,确保多个进程能够正确地共享同一块内存。
  • key是一个逻辑上的标识符,用于创建或查找共享内存段;而shmid是一个物理上的标识符,用于具体的操作共享内存段。
  • key是静态的,一旦生成就不会改变;而shmid是动态的,每次创建共享内存段时,操作系统都会返回一个新的shmid
  • key用于解决“找到”共享内存的问题,而shmid用于解决“操作”共享内存的问题。

如何获取 shmid ?

#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);
参数:

key:用于标识共享内存段的键值。这个键值通常通过 ftok函数生成。

size共享内存段的大小(以字节为单位)。如果key对应的一个共享内存段已经存在,那么这个参数将被忽略。在内核中,共享内存的大小以 4KB 为基本单位,且你只能用你申请的大小,为了避免空间浪费,建议 size 的大小是 n*4KB

shmflg:一组标志位,用于控制创建和访问共享内存段的行为。


常见的标志位包括:

  • IPC_CREAT:如果指定的 key对应的共享内存段不存在,则创建一个新的共享内存段;如果存在,则直接获取该共享内存。传该参数得到的共享内存不一定是新的,可能是之前创建的。
  • IPC_EXCL:独自使用时没有意义。
  • IPC_EXCL|IPC_CREATkey对应的共享内存段如果不存在,就会创建一个新的共享内存;如果已经存在,则shmget会失败并返回 EEXIST错误传该参数得到的共享内存一定是新的!
  • 权限位:如0666,用于设置共享内存段的访问权限
返回值:
  • 如果成功shmget返回一个非负整数,即 shmid
  • 如果失败返回 -1,并且设置 errno以指示失败的原因。

封装:

int CreateShmOrDie(key_t key, int size, int flag)
{//得到共享内存的shmidint shmid=shmget(key,size,flag);if(shmid<0)//创建失败{cerr<<" shmget failed, errno:"<<errno<<", errstring:"<<strerror(errno)<<endl;exit(2);}return shmid;//创建成功
}int CreateShm(key_t key,int size)
{//创建一个新的共享内存,并设置权限return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}int GetShm(key_t key,int size)
{return CreateShmOrDie(key,size,IPC_CREAT);
}

shmctl 函数 -- 控制共享内存

#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数:

shmid:共享内存段的标识符,通常通过shmget函数获得。

cmd:命令代码,用于指定要执行的操作。


cmd参数的常用值:

  • IPC_STAT:获取共享内存段的状态信息,并存储在buf指向的结构体中。
  • IPC_RMID:删除共享内存段。

buf:指向struct shmid_ds类型的指针,struct shmid_ds包含有关共享内存段的各种信息,包括权限、所有者等。若不需要该参数,可以传 NULL 。

返回值:

  • 如果shmctl函数成功执行,它返回 0
  • 如果shmctl函数执行失败,它返回 -1,并且会设置 errno 以指示失败的原因。

封装:

删除共享内存:
void DeleteShm(int shmid)
{int n=shmctl(shmid,IPC_RMID,nullptr);if(n<0)cerr<<" Delete failed,errno:"<<errno<<", errstring:"<<strerror(errno)<<endl;elsecout<<" Delete success, shmid:"<<shmid<<endl;
}
获得共享内存的状态:
string ToHex(key_t k)//将 key 值转为十六进制
{char buffer[1024];//用C语言方便用 %x 直接转为十六进制snprintf(buffer,sizeof(buffer),"0x%x",k);return buffer;
}void DebugShm(int shmid)
{struct shmid_ds shmds;int n = shmctl(shmid, IPC_STAT, &shmds);if (n < 0)cerr << " shmctl failed " << endl;else{std::cout << "shmds.shm_segsz: " << shmds.shm_segsz << std::endl;//共享内存的大小std::cout << "shmds.shm_nattch:" << shmds.shm_nattch << std::endl;//有多少个进程挂接std::cout << "shmds.shm_ctime:" << shmds.shm_ctime << std::endl;//上一次挂接或取消挂接的时间std::cout << "shmds.shm_perm.__key:" << ToHex(shmds.shm_perm.__key) << std::endl;//对应的key}
}

shmat 函数 -- 将共享内存挂接到进程地址空间

上面的 shmget 函数只是创建了一个共享内存,但是这个共享内存并没有映射到进程的地址空间,还不属于进程,所以需要调用函数,把该共享内存挂接到进程地址空间中。

#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:

shmid:共享内存段的标识符,通常通过shmget函数获得。

shmaddr:指定共享内存段在进程地址空间中的起始地址。如果设置为 NULL,则由系统选择一个合适的地址。

shmflg:一组标志位,用于控制共享内存段的映射行为


常用的标志位包括:

  • SHM_RDONLY只读方式映射共享内存段。
  • SHM_RND:映射地址将是 4K 对齐的随机地址。
  • SHM_REMAP:如果共享内存段已经存在于进程地址空间中,则重新映射共享内存段。

当 shmflg设为 0 时,意味着不使用任何特定的标志位,默认按照系统默认的方式进行映射。具体来说:

  • 默认映射方式:系统会选择一个适合的地址来映射共享内存段。
  • 读写模式:默认情况下,映射是以读写模式进行的,而不是只读模式。
  • 无特殊要求:不强制使用特定的映射地址,也不要求重新映射已经存在的共享内存段。

返回值:

  • 如果成功shmat返回一个指向共享内存段的指针
  • 如果失败,返回(void *)-1,并且会设置 errno以指示失败的原因。

    void*(空指针类型)是C语言中的一种指针类型,表示一个未指定类型的指针。void* 可以存储任何类型的指针值,并且在使用时需要显式转换为目标类型的指针

封装:

void *ShmAttach(int shmid)
{void* addr=shmat(shmid,nullptr,0);if((long long int)addr==-1){//挂接失败cerr<<" attach failed,errno:"<<errno<<", errstring:"<<strerror(errno)<<endl;return nullptr;}else{//挂接成功return addr;}
}

shmdt 函数 -- 分离

shmdt(shared memory detach)函数用于将先前通过shmat函数映射到进程地址空间的共享内存段分离(detach)出来。分离后,共享内存段仍然存在于系统中,只是不再映射到当前进程的地址空间中。这意味着进程不能再直接访问这块共享内存中的数据。

#include <sys/shm.h>int shmdt(const void *shmaddr);

参数:

shmaddr:指向先前通过shmat函数映射到进程地址空间的共享内存段的指针。

返回值:

  • 如果 shmdt函数成功执行,它返回 0。
  • 如果 shmdt函数执行失败,它返回 -1,并设置 errno以指示失败的原因。

封装:

void ShmDetach(void *addr)
{int n=shmdt(addr);if(n<0){cerr<<" Detach failed,errno:"<<errno<<", errstring:"<<strerror(errno)<<endl;}
}

相关文章:

Linux -- 共享内存(1)

目录 共享内存 共享内存相关函数 ftok 函数 -- 获取 key 值 什么是 key&#xff1f; 如何生成 key &#xff1f; 参数&#xff1a; 返回值&#xff1a; 封装&#xff1a; shmget 函数 -- 获取 shmid 值 什么是 shmid&#xff1f; shmid 和 key 的区别&#xff1f; …...

冒泡排序和二分查找--go

冒泡排序的逻辑 二分查找的逻辑 func bubbleSort(arr *[5]int){//冒泡排序fmt.Println(*arr)temp : 0for j : len(*arr); j > 0; j-- {for i : 0; i < j-1; i {temp (*arr)[i]if((*arr)[i] > (*arr)[i1]){(*arr)[i] (*arr)[i1](*arr)[i1] temp}}} }func binaryF…...

springboot RedisTemplate支持多个序列化方式

前提纪要&#xff1a;因为业务变动&#xff0c;需要在原先只支持protobuf的前提序列化的前提下&#xff0c;新增正常的序列化读取数据所以在原先的基础上进行优化。文章用于记忆。 话不多说直接上代码 Configuration AutoConfigureAfter(RedisAutoConfiguration.class) Import…...

开源项目-拍卖管理系统

哈喽&#xff0c;大家好&#xff0c;今天主要给大家带来一个开源项目-拍卖管理系统 拍卖管理系统主要有拍卖品管理&#xff0c;我的拍卖&#xff0c;拍卖详情&#xff0c;拍卖品信息修改&#xff0c;发布拍卖品等功能 登录 拍卖商品管理 主要用于查看、竞拍拍卖商品的信息 我…...

Python小游戏14——雷霆战机

首先&#xff0c;你需要确保安装了Pygame库。如果你还没有安装&#xff0c;可以使用pip来安装&#xff1a; bash pip install pygame 代码如下&#xff1a; python import pygame import sys import random # 初始化Pygame pygame.init() # 设置屏幕大小 screen_width 800 scr…...

81页PPT | 企业数字化底座与数字化转型方案

方案内容涵盖了企业数字化转型的议程、集团管理分析类应用建设的现状与问题、数字化建设的目标、预期收益、总体架构、数据产生层、数据交换层、数据存储层、数据应用层、数据管控层等多个方面。方案详细描述了数据从产生、交换、存储到应用的全过程&#xff0c;以及如何通过数…...

R语言笔记(五):Apply函数

文章目录 一、Apply Family二、apply(): rows or columns of a matrix or data frame三、Applying a custom function四、Applying a custom function "on-the-fly"五、Applying a function that takes extra arguments六、Whats the return argument?七、Optimized…...

Newsqueak:在 Go 之前的一门语言

写在前面 学习一个东西的一种很好的方法&#xff0c;就是去了解这个东西的历史。在我们学习 Go 的过程中&#xff0c;同样也可以去了解下在 Go 之前的一些事情。 内容 Rob Pike 是 Go 语言的作者之一&#xff0c;早年他在贝尔实验室工作&#xff0c;也是 Unix 团队的成员。 …...

世界酒中国菜与另可数字平台达成战略合作

世界酒中国菜与另可数字平台达成战略合作&#xff0c;共推行业发展新高度 近日&#xff0c;在行业内引起广泛关注的“世界酒中国菜”项目&#xff0c;与“另可”数字平台成功举行了战略合作签约仪式。这一重要合作不仅是双方发展历程中的重要里程碑&#xff0c;更是继世界酒中…...

ElasticSearch基础篇——概念讲解,部署搭建,使用RestClient操作索引库和文档数据

目录 一、概念介绍 二、Elasticsearch的Docker容器安装 2.1拉取elasticsearch的镜像文件 2.2运行docker命令启动容器 2.3通过访问端口地址查看部署情况 三、安装Kibana容器 3.1拉取Kibana镜像容器指令&#xff08;默认拉取最新版本&#xff09;&#xff1a; 3.2拉取完…...

k8s 二进制部署安装(一)

目录 环境准备 初始化操作系统 部署docker 引擎 部署 etcd 集群 准备签发证书环境 部署 Master01 服务器相关组件 apiserver scheduler controller-manager.sh admin etcd 存储了 Kubernetes 集群的所有配置数据和状态信息&#xff0c;包括资源对象、集群配置、元数据…...

115页PPT华为管理变革:制度创新与文化塑造的核心实践

集成供应链&#xff08;ISC&#xff09;体系 集成供应链&#xff08;ISC&#xff09;体系是英文Integrated Supply Chain的缩写&#xff0c;是一种先进的管理思想&#xff0c;它指的是由相互间提供原材料、零部件、产品和服务的供应商、合作商、制造商、分销商、零售商、顾客等…...

ubuntu限制网速方法

sudo apt-get install trickle sudo trickle -d <下载速度> -u <上传速度> <命令>例如git clone sudo trickle -d 1024 git clone http://xxxxxxxxxx.git如果想简化指令可以在bashrc中添加如下指令 alias gitttrickle -u 1024 gitgitt为自定义 使用方法&am…...

三品PLM研发管理系统:企业产品研发过程的得力助手

三品PLM系统&#xff1a;全方位赋能企业产品生命周期管理的优选方案 在当今竞争激烈的市场环境中&#xff0c;产品生命周期管理PLM系统已成为企业实现高效、灵活和创新产品开发的关键工具。PLM系统集成了信息技术、先进管理思想与企业业务流程&#xff0c;旨在帮助企业优化产品…...

PyCharm 添加不了 Anaconda 环境

经常会遇到 PyCharm 无法添加新创建的 Anaconda 环境&#xff0c; Setting --> Python Interpreter --> Add Python Interperter --> Conda Environment 中为空&#xff0c;即使打开右侧文件夹路径按钮&#xff0c;选择新创建的 conda 环境&#xff0c;也无法找到 pyt…...

Leetcode 二叉树的右视图

好的&#xff0c;我来用中文详细解释这段代码的算法思想。 问题描述 题目要求给定一个二叉树的根节点&#xff0c;从树的右侧看过去&#xff0c;按从上到下的顺序返回看到的节点值。即&#xff0c;我们需要找到每一层的最右侧节点并将其加入结果中。 算法思想 这道题可以通…...

console.log(“res.data = “ + JSON.stringify(res.data));

res.data[object Object] 说明你在控制台打印 res.data 时&#xff0c;它是一个 JavaScript 对象&#xff0c;而不是字符串。这种情况下&#xff0c;console.log 输出的 [object Object] 表示它无法直接显示对象的内容。 要查看 res.data 的实际内容&#xff0c;你需要将其转换…...

node和npm

背景&#xff08;js&#xff09; 1、为什么js能操作DOM和BOM? 原因&#xff1a;每个浏览器都内置了DOM、BOM这样的API函数 2、浏览器中的js运行环境&#xff1f; v8引擎&#xff1a;负责解析和执行js代码 内置API&#xff1a;由运行环境提供的特殊接口&#xff0c;只能在所…...

通过四元数求机器人本体坐标旋转量

是的&#xff0c;通过两次姿态数据&#xff08;以四元数表示&#xff09;的差值&#xff0c;可以确定机器人在两个时刻之间的旋转角度变化。具体步骤如下&#xff1a; 获取四元数&#xff1a;假设两个时刻的四元数分别为 ( q_1 ) 和 ( q_2 )。计算四元数的差值&#xff1a; 将…...

CodeQL学习笔记(2)-QL语法(递归)

最近在学习CodeQL&#xff0c;对于CodeQL就不介绍了&#xff0c;目前网上一搜一大把。本系列是学习CodeQL的个人学习笔记&#xff0c;根据个人知识库笔记修改整理而来的&#xff0c;分享出来共同学习。个人觉得QL的语法比较反人类&#xff0c;至少与目前主流的这些OOP语言相比&…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...