图解Linux内核(基于6.x):解读Linux内存反向映射之匿名映射

文章目录

  • 📑前言
  • 一、匿名映射的mapping
  • 二、推荐阅读
    • 2.1 一图速览
    • 2.2 内容简介

image.png

📑前言

内存映射中,我们经常讨论的是由虚拟内存定位物理内存(也就是folio或者page),实际上在很多场景中(比如内存回收),会涉及反向的操作,也就是反向映射。所谓反向映射,就是给定一个folio(page),将映射它的PTE(页表项)找出来。接下来我们来详细分析一下它的原理吧(本文仅分析匿名映射部分)。

一、匿名映射的mapping

匿名映射中,mapping可以用来找到anon_vma,anon_vma关联vma,通过folio和vma,就可以得出映射的虚拟地址address,最终由address和vma定位PTE,如图1所示。


图1.匿名folio定位address示意图
图1中基本都是直来直去的关系,除了anon_vma和vma,它们实际上是多对多的关系,由anon_vma_chain结构体(以下简称avc)辅助实现。
我们从mmap返回,vma还没有映射任何物理页的情景说起。
第一次访问vma区间的地址,导致缺页异常。内核调用do_anonymous_page,申请一页内存,完成映射。
由于这是vma区间内的第一次缺页异常,vma相关的anon_vma和avc还不存在,处理异常的过程中会准备好它们,然后调用page_add_new_anon_rmap为该page(folio)建立反向映射,将anon_vma赋值给mapping字段。关键代码片段如下。

struct anon_vma *anon_vma = vma->anon_vma;anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; 
WRITE_ONCE(page->mapping, (struct address_space *) anon_vma); 
page->index = linear_page_index(vma, address);

代码中的address就是映射的虚拟地址,page->index实际上是page offset,该page在文件中的偏移量,也就是映射的是文件的第几页,计算代码如下。

pgoff = (address - vma->vm_start) >> PAGE_SHIFT; 
pgoff += vma->vm_pgoff;  
return pgoff;

vma->vm_pgoff是vma的起始地址对应的文件的page offset。
匿名映射没有对应文件,它的vma->vm_pgoff等于vma->vm_start >> PAGE_SHIFT。
这里需要明确一下,从内核的角度看,我们以MAP_ANONYMOUS调用mmap等完成的映射并不一定是匿名映射。置位MAP_SHARED的情况下,内核会生成“假”(pseudo)文件与之对应(shmem_zero_setup),就不是匿名的了,vma->vm_pgoff等于0。只有MAP_ANONYMOUS和 MAP_PRIVATE同时置位的情况下才是内核承认的匿名映射。
这里有以下两点需要注意。

  1. 整个vma可能会有多个页,它们的mapping字段是相等的,不等的是index字段。
  2. anon_vma和vma的关系并不依赖page,哪怕是vma映射中的其中一部分page改变映射了,从anon_vma到vma的路径并不会变。

单个进程的反向映射建立了,如图2所示。anon_vma到vma实际上是通过区间树(interval tree)实现的,为了看起来简洁些图中使用链表代替。


图2.匿名映射单个进程反向映射示意图
接下来考虑创建子进程的场景。在新进程创建的过程中,有些情况会调用dup_mmap复制原进程的内存空间,dup_mmap会复制vma,然后调用anon_vma_fork。anon_vma_fork会为新进程申请anon_vma,建立反向映射,完成后如图3所示。

图3.创建子进程后匿名映射示意图
新进程创建完成后,从page->mapping出发,可以遍历所有映射它的PTE了。
再考虑COW的场景,缺页异常申请新的一页,将原页的内存复制到新页中,然后使用新页更新映射,根据前文中“需要注意的第2点”可以得出图4中的结果。

图4.COW发生后匿名映射示意图
可以看到,从原页依然可以遍历到没有映射它的vma(请仔细理解anon_vma和vma的关系并不依赖page),从新页出发倒是没有这个烦恼。
我们肯定不希望操作原页的时候会影响到没有映射它的vma,所以得到某个vma后,需要做进一步检查,原理是拿原页的pfn区间(一个folio可能包含多个连续的物理页)和vma映射的物理页的pfn做比较,落在区间内才是有效的,由check_pte实现。
有了以上的铺垫,我们可以分析匿名页的反向映射了,由rmap_walk_anon实现,核心逻辑如下。

void rmap_walk_anon(struct folio *folio,  struct rmap_walk_control *rwc, bool locked)
{  struct anon_vma *anon_vma;  pgoff_t pgoff_start, pgoff_end;  struct anon_vma_chain *avc;if (locked) {    anon_vma = folio_anon_vma(folio);    //1  } else {    anon_vma = rmap_walk_anon_lock(folio, rwc);  }pgoff_start = folio_pgoff(folio);    //2  pgoff_end = pgoff_start + folio_nr_pages(folio) - 1;  anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root,pgoff_start, pgoff_end) {struct vm_area_struct *vma = avc->vma;unsigned long address = vma_address(&folio->page, vma);    //3if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg))    //4      continue;    if (!rwc->rmap_one(folio, vma, address, rwc->arg))      break;    if (rwc->done && rwc->done(folio))      break;  }if (!locked)    anon_vma_unlock_read(anon_vma);
}

第1步,获得anon_vma,是给anon_vma->mapping赋值(见前文代码片段)的反过程。
第2步,调用folio_pgoff得到pgoff_start,然后根据folio的页数得到pgoff_end,用作遍历interval tree的时候筛选vma。folio_pgoff返回folio->index,赋值过程也见前文代码片段。
第3步,根据folio和vma计算得到虚拟地址,不考虑多页的情况下,计算过程如下。

pgoff_in_vma = page->index - vma->vm_pgoff
address = vma->vm_start + (pgoff_in_vma << PAGE_SHIFT)

这个计算过程对匿名映射和文件映射都适用。vma->vm_pgoff是vma基于文件的page offset,vma->vm_start是vma区间的其实虚拟地址,加上当前页在vma内的offset就可以得到虚拟地址了。匿名映射没有文件,vma->vm_pgoff等于vma->vm_start >> PAGE_SHIFT,用来做计算也是没有问题的。
这里anon_vma_interval_tree_foreach会筛选树上符合pgoff_start, pgoff_end区间的vma,难道anon_vma上的vma可以有不同的pgoff区间吗?答案是肯定的,为了简化问题,我们之前回避了anon_vma的重复利用问题,同一个进程符合条件的vma是可以共享anon_vma的(find_mergeable_anon_vma)。从这个角度看,vma->vm_pgoff等于vma->vm_start >> PAGE_SHIFT是合理的,同一个进程不同的vma计算得到的vma->vm_pgoff也不同。
第4步,调用rmap_walk_control(代码中简称rwc)提供的回调函数。rmap_walk_anon提供了遍历vma的方法,至于对每个vma做什么,是由调用它的函数决定的,比如folio_referenced函数希望遍历PTE,查看folio被不同PTE访问的次数,它的rwc定义如下。

struct folio_referenced_arg pra = {.mapcount = folio_mapcount(folio),.memcg = memcg,
};
struct rmap_walk_control rwc = {.rmap_one = folio_referenced_one,.arg = (void *)&pra,.anon_lock = folio_lock_anon_vma_read,.try_lock = true,
};

另外,rmap_walk_anon给出了vma、address和folio,但没有得到PTE,这个任务只能由rwc的回调函数自行完成,不过内核提供了page_vma_mapped_walk函数辅助完成该任务。

二、推荐阅读

2.1 一图速览


《图解Linux内核(基于6.x)》
京东:https://item.jd.com/14577130.html

2.2 内容简介

  • 全书共五篇,以从易到难的顺序详细剖析了Linux内核开发的核心技术。“知识储备篇”介绍了Linux的数据结构、中断处理、内核同步和时间计算等内容,这些是理解后续章节的前提;之后通过“内存管理篇”“文件系统篇”“进程管理篇”详细介绍了Linux的三大核心模块;最后的“综合应用篇”则融合了前面诸多模块知识展示了Linux内核开发在操作系统、智能设备、驱动、通信、芯片、云计算和人工智能等热点领域的应用。书中的重点、难点均配有图表、代码和实战案例,力求直观、清晰。
  • 学习本书的读者需要熟悉C语言,建议对Linux内核有一定了解。推荐初学者按照本书的编排顺序阅读,而熟悉Linux内核的读者可以跳过知识储备篇,直接从三大核心模块篇进行阅读。

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

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

相关文章

linux写代码环境和工具

基础指令 目录 前言 二、yum工具的使用 1.yum是什么&#xff1f; 2.查看软件包 3.配置sudo 4.如何卸载软件 三、vim的使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4.简单vim配置 四、Linux编译器-gcc/g使用 1、格式 2、gcc选项 3.gcc/g工作和…

Vue CLI,Vue Router,Vuex

前言 Vue CLI、Vue Router 和 Vuex 都是 Vue.js 生态系统中的重要组成部分&#xff0c;它们在构建 Vue 应用程序时扮演着关键角色。 Vue CLI Vue CLI 介绍 Vue CLI 是 Vue.js 的官方命令行工具&#xff0c;用于快速搭建 Vue.js 项目。它提供了一个图形界面&#xff08;通过…

工程打包与运行

黑马程序员Spring Boot2 文章目录 先点击cean&#xff0c;确保打包之前是个干净的环境点击package进行打包&#xff0c;打包成功之后可以看到target文件夹下的文件 到项目目录下使用终端打开&#xff0c;并使用以下命令运行打包好的程序 如果遇到没有主清单属性的问题&#xff…

搜维尔科技邀您共赴2024第四届轨道车辆工业设计国际研讨会

会议内容 聚焦“创新、设计、突破”&#xff0c;围绕“面向生命健康、可持续发展的轨道交通系统” 为主题&#xff0c;从数字化、智能化、人性化、绿色发展等方面&#xff0c;探索轨道交通行业的设计新趋势及发展新机遇。 举办时间 2024年7月10日-12日 举办地点 星光岛-青岛融…

5.音视频基础 FLV

目录 简说FLV FLV Header FLV Body Tag Header ​编辑Tag Data Audio Data Video Data Script Data 简说FLV FLV格式可以包含音频、视频和文本数据&#xff0c;并且可以在网络上进行流媒体传输。优点是文件大小较小&#xff0c;压缩效率高&#xff0c;并且可以在较低…

WiFi/BLE芯片(1):英飞凌

前言: 大部分客户很少直接接触到WiFi/Bluetooth的芯片,一般是直接封装到了模块中,隔了一层。具体到芯片而言,WiFi/BLE芯片,芯片厂家有:Qualcomm高通、broadcom博通、Infineon英飞凌、Nordic诺迪科、Espressof乐鑫等。而英飞凌这块产品也是很丰富的,低功耗、距离等性能指…

飞创直线模组厂家,为高精度运动系统提供直驱技术解决方案

飞创Faster motion是国内一家专业的直线模组厂家&#xff0c;致力于研发、设计、生产超长行程、超高速度、超高精度、超重负载以及速度平稳的单轴和多轴直线电机模组&#xff0c;为高速、高精度运动平台提供直驱技术解决方案。 飞创直线模组其生产的单轴、双轴、龙门、多轴模组…

化工电力系统RFID无线测温技术的重要性。

在现代工业体系中&#xff0c;化工电力系统的安全与效率对于整个生产链的顺畅运行至关重要。在日常工作中,由于设备制造的原因,设备受环境污染的原因、设备长期运行、严重超载运行、触点氧化、电弧冲击等原因造接触电阻增大,因此在运行时往往不断发热,温度不断上升,给设备安全运…

Leetcode Hot100之双指针

1. 移动零 题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。解题思路 双指针遍历一遍即可解决: 我们定义了两个指针 i 和 j&#xf…

C++ Windows Hook使用

GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form. /*挂载钩子 setdll /d:C:\Users\g\source\repos\LotTest\Release\lotDll.dll C:\Users\g\source\repos\LotTest…

Java特性之设计模式【访问者模式】

一、访问者模式 概述 在访问者模式&#xff08;Visitor Pattern&#xff09;中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。通过这种方式&#xff0c;元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式&…

WPF三方UI库全局应用MessageBox样式(.NET6版本)

一、问题场景 使用HandyControl简写HC 作为基础UI组件库时&#xff0c;希望系统中所有的MessageBox 样式都使用HC的MessageBox&#xff0c;常规操作如下&#xff1a; 在对应的xxxx.cs 顶部使用using 指定特定类的命名空间。 using MessageBox HandyControl.Controls.Message…

js语法---理解反射Reflect对象和代理Proxy对象

Reflect 基本要点 反射&#xff1a;reflect是一个内置的全局对象&#xff0c;它的作用就是提供了一些对象实例的拦截方法&#xff0c;它的用法和Math对象相似&#xff0c;都只有静态方法和属性&#xff0c;同时reflect也没有构造器&#xff0c;无法通过new运算符构建实例对象&…

xcode和iPhone真机或者watch真机连接问题

1.如果真机是第一次连接xocde&#xff0c;就需要开启真机上的开发者模式&#xff0c;开启开发者模式的方式&#xff1a; iphone/ipad开启方式: 设置 > 隐私与安全 > 开发者模式 > 开启&#xff0c;然后重启就可以了 watch设置&#xff1a;很麻烦&#xff0c;看文章…

现代谱估计分析信号的功率谱(1)---AR 模型谱估计

本篇文章是博主在通信等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对通信等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在通信领域笔记&#xff1a;…

进阶篇06——锁

概述 全局锁 表级锁 表锁 元数据锁 元数据锁是系统自动加的&#xff0c;不需要我们手动执行命令添加。 意向锁 意向锁和元数据锁一样&#xff0c;也是在加行锁的时候自动给表加上相应的意向锁&#xff0c;不需要我们手动添加。 行级锁 行锁 读锁和读锁兼容&#xff0c;写锁…

易舟云财务软件:开启云记账新时代

在数字化浪潮的推动下&#xff0c;财务管理正经历着深刻的变革。易舟云财务软件&#xff0c;作为一款引领时代的云记账平台&#xff0c;以其卓越的功能和便捷的操作&#xff0c;为企业带来了全新的财务管理体验。 云记账&#xff0c;财务管理的未来趋势 云记账&#xff0c;即基…

免费试用【汇通动态域名】体验test.htdns.cn

汇通动态域名下载地址&#xff1a; http://www.htsoft.com.cn/htsoft/htdnssoft.html 下载后汇通动态域名是绿色软件&#xff0c;不用安装&#xff0c;直接运行htdns.exe 点注册 二级域名地方改成您自己要的域名&#xff0c;我输入的是test,点保存&#xff0c;提示让您输入密…

2024年618成交额达7428亿 淘宝京东618交易额数据对比排名

2024年618年中大促已经基本落下帷幕&#xff0c;作为上半年最重要的电商节日&#xff0c;今年的618交易额有多少&#xff1f;今年的交易数据有哪些变化&#xff1f;我们来一起看一下&#xff01; 根据星图监测数据显示&#xff0c;2024年618期间&#xff08;天猫5月20日20: 00-…

海外盲盒APP开发,盲盒出海热!

当下&#xff0c;盲盒作为一种热门的娱乐休闲模式&#xff0c;在全球消费市场中都非常火热&#xff0c;各种热门盲盒商品刚一上线就受到了秒杀&#xff0c;受到了各地年轻消费者的追捧&#xff01; 盲盒全球化对于我国盲盒企业来说是一个新的机会&#xff0c;有助于我国盲盒快…