阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

一文搞定 | Linux 共享内存原理

401次阅读
没有评论

共计 2371 个字符,预计需要花费 6 分钟才能阅读完成。

在 Linux 系统中,每个进程都有独立的虚拟内存空间,也就是说不同的进程访问同一段虚拟内存地址所得到的数据是不一样的,这是因为不同进程相同的虚拟内存地址会映射到不同的物理内存地址上。

但有时候为了让不同进程之间进行通信,需要让不同进程共享相同的物理内存,Linux 通过 共享内存 来实现这个功能。下面先来介绍一下 Linux 系统的共享内存的使用。

共享内存使用

1. 获取共享内存

要使用共享内存,首先需要使用 shmget() 函数获取共享内存,shmget() 函数的原型如下:

一文搞定 | Linux 共享内存原理

  • 参数 key 一般由 ftok() 函数生成,用于标识系统的唯一 IPC 资源。
  • 参数 size 指定创建的共享内存大小。
  • 参数 shmflg 指定 shmget() 函数的动作,比如传入 IPC_CREAT 表示要创建新的共享内存。

函数调用成功时返回一个新建或已经存在的的共享内存标识符,取决于 shmflg 的参数。失败返回 -1,并设置错误码。

2. 关联共享内存

shmget() 函数返回的是一个标识符,而不是可用的内存地址,所以还需要调用 shmat() 函数把共享内存关联到某个虚拟内存地址上。shmat() 函数的原型如下:

一文搞定 | Linux 共享内存原理

  • 参数 shmid 是 shmget() 函数返回的标识符。
  • 参数 shmaddr 是要关联的虚拟内存地址,如果传入 0,表示由系统自动选择合适的虚拟内存地址。
  • 参数 shmflg 若指定了 SHM_RDONLY 位,则以只读方式连接此段,否则以读写方式连接此段。

函数调用成功返回一个可用的指针(虚拟内存地址),出错返回 -1。

3. 取消关联共享内存

当一个进程不需要共享内存的时候,就需要取消共享内存与虚拟内存地址的关联。取消关联共享内存通过 shmdt() 函数实现,原型如下:

一文搞定 | Linux 共享内存原理

  • 参数 shmaddr 是要取消关联的虚拟内存地址,也就是 shmat() 函数返回的值。

函数调用成功返回 0,出错返回 -1。

共享内存使用例子

下面通过一个例子来介绍一下共享内存的使用方法。在这个例子中,有两个进程,分别为 进程 A 和 进程 B,进程 A 创建一块共享内存,然后写入数据,进程 B 获取这块共享内存并且读取其内容。

进程 A

一文搞定 | Linux 共享内存原理

进程 B

一文搞定 | Linux 共享内存原理

测试时先运行进程 A,然后再运行进程 B,可以看到进程 B 会打印出“Hello World”,说明共享内存已经创建成功并且读取。

共享内存实现原理

我们先通过一幅图来了解一下共享内存的大概原理,如下图:

一文搞定 | Linux 共享内存原理

通过上图可知,共享内存是通过将不同进程的虚拟内存地址映射到相同的物理内存地址来实现的,下面将会介绍 Linux 的实现方式。

在 Linux 内核中,每个共享内存都由一个名为 struct shmid_kernel 的结构体来管理,而且 Linux 限制了系统最大能创建的共享内存为 128 个。通过类型为 struct shmid_kernel 结构的数组来管理,如下:

一文搞定 | Linux 共享内存原理

从注释可以知道 struct shmid_kernel 结构体各个字段的作用,比如 shm_npages 字段表示共享内存使用了多少个内存页。而 shm_pages 字段指向了共享内存映射的虚拟内存页表项数组等。

另外 struct shmid_ds 结构体用于管理共享内存的信息,而 shm_segs 数组 用于管理系统中所有的共享内存。

shmget() 函数实现

通过前面的例子可知,要使用共享内存,首先需要调用 shmget() 函数来创建或者获取一块共享内存。shmget() 函数的实现如下:

一文搞定 | Linux 共享内存原理

shmget() 函数的实现比较简单,首先调用 findkey() 函数查找值为 key 的共享内存是否已经被创建,findkey() 函数返回共享内存在 shm_segs 数组 的索引。如果找到,那么直接返回共享内存的标识符即可。否则就调用 newseg() 函数创建新的共享内存。newseg() 函数的实现也比较简单,就是创建一个新的 struct shmid_kernel 结构体,然后设置其各个字段的值,并且保存到 shm_segs 数组 中。

shmat() 函数实现

shmat() 函数用于将共享内存映射到本地虚拟内存地址,由于 shmat() 函数的实现比较复杂,所以我们分段来分析这个函数:

一文搞定 | Linux 共享内存原理

上面这段代码主要通过 shmid 标识符来找到共享内存描述符,上面说过系统中所有的共享内存到保存在 shm_segs 数组中。

一文搞定 | Linux 共享内存原理

上面的代码主要找到一个可用的虚拟内存地址,如果在调用 shmat() 函数时没有指定了虚拟内存地址,那么就通过 get_unmapped_area() 函数来获取一个可用的虚拟内存地址。

一文搞定 | Linux 共享内存原理

上面的代码主要通过调用 kmem_cache_alloc() 函数创建一个 vm_area_struct 结构,在内存管理一章知道,vm_area_struct 结构用于管理进程的虚拟内存空间。

一文搞定 | Linux 共享内存原理

上面的代码主要是设置刚创建的 vm_area_struct 结构的各个字段,比较重要的是设置其 vm_ops 字段为 shm_vm_ops,shm_vm_ops 定义如下:

一文搞定 | Linux 共享内存原理

shm_vm_ops 的 nopage 回调为 shm_nopage() 函数,也就是说,当发生页缺失异常时将会调用此函数来恢复内存的映射。

从上面的代码可看出,shmat() 函数只是申请了进程的虚拟内存空间,而共享内存的物理空间并没有申请,那么在什么时候申请物理内存呢?答案就是当进程发生缺页异常的时候会调用 shm_nopage() 函数来恢复进程的虚拟内存地址到物理内存地址的映射。

shm_nopage() 函数实现

shm_nopage() 函数是当发生内存缺页异常时被调用的,代码如下:

一文搞定 | Linux 共享内存原理

shm_nopage() 函数的主要功能是当发生内存缺页时,申请新的物理内存页,并映射到共享内存中。由于使用共享内存时会映射到相同的物理内存页上,从而不同进程可以共用此块内存。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-12-03发表,共计2371字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7803391
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024 程序员】我劝你赶紧去免费领一个 AWS、华为云等的主机 每年 10 月 24 日,程序员们都会迎来...
免费领取huggingface的2核16G云服务器,超简单教程

免费领取huggingface的2核16G云服务器,超简单教程

免费领取 huggingface 的 2 核 16G 云服务器,超简单教程 前言 HuggingFace.co...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸 前言 作为天天跟架构图、拓扑图死磕的...
零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face 免费服务器 +Docker 快速部署 HertzBeat 监控平台 ...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛NAS-14:解锁公网自由!Lucky功能工具安装使用保姆级教程

星哥带你玩飞牛 NAS-14:解锁公网自由!Lucky 功能工具安装使用保姆级教程 作为 NAS 玩家,咱们最...
星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

  星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸

一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸 前言 作为天天跟架构图、拓扑图死磕的...