linux内存管理(八)- 反向映射RMAP

news/2024/10/5 5:13:54

这里有一篇博客讲的不错。linux内存管理笔记(三十八)----反向映射_linux 反向映射-CSDN博客

页表是把虚拟地址映射到物理页面,但是如何根据一个物理页找到所有映射它的pte呢?答案是用反向映射Reverse Mapping(RMAP)。这在页面回收中很有用。回收页面需要将到物理页的映射断开(改一下pte),前提是找到所有映射的pte,那就必须在page结构中留下线索,这就是mapping字段。

在讲page结构时我们提到过mapping可以指向匿名页的anon_vma结构,这个结构是反向映射的关键之一。

struct anon_vma {struct anon_vma *root;        /* Root of this anon_vma tree */struct rw_semaphore rwsem;    /* W: modification, R: walking the list */
    atomic_t refcount;
    unsigned long num_children;/* Count of VMAs whose ->anon_vma pointer points to this object. */unsigned long num_active_vmas;struct anon_vma *parent;    /* Parent of this anon_vma */struct rb_root_cached rb_root;  //avc结构会链接到这棵rbtree上
};

除了anon_vma(AV)还有一个AVC(anon_vma_chain)结构。

/** The copy-on-write semantics of fork mean that an anon_vma* can become associated with multiple processes. Furthermore,* each child process will have its own anon_vma, where new* pages for that process are instantiated.** This structure allows us to find the anon_vmas associated* with a VMA, or the VMAs associated with an anon_vma.* The "same_vma" list contains the anon_vma_chains linking* all the anon_vmas associated with this VMA.* The "rb" field indexes on an interval tree the anon_vma_chains* which link all the VMAs associated with this anon_vma.*/
struct anon_vma_chain {struct vm_area_struct *vma;struct anon_vma *anon_vma;struct list_head same_vma;   /* locked by mmap_lock & page_table_lock */struct rb_node rb;            /* locked by anon_vma->rwsem */unsigned long rb_subtree_last;
#ifdef CONFIG_DEBUG_VM_RBunsigned long cached_vma_start, cached_vma_last;
#endif
};

看注释可知AVC可以通过rb_node链接到anon_vma的rbtree上,这个rbtree会链接所有与AV相关的VMA。也可以通过same_vma链表链接所有与该VMA相关的AV。AVC是anon_vma和vma的枢纽,可以让三者相互找到另外两方。

上图是一个简单的情形,描述三者之间的关系,这对理解后面反向映射的应用很重要。

反向映射的应用。

使用反向映射最常见的是在回收页面,try_to_unmap是其重要函数。

void try_to_unmap(struct folio *folio, enum ttu_flags flags)
{struct rmap_walk_control rwc = {.rmap_one = try_to_unmap_one,.arg = (void *)flags,.done = folio_not_mapped,.anon_lock = folio_lock_anon_vma_read,};if (flags & TTU_RMAP_LOCKED)rmap_walk_locked(folio, &rwc);elsermap_walk(folio, &rwc);
}

rmap_walk

void rmap_walk(struct folio *folio, struct rmap_walk_control *rwc)
{if (unlikely(folio_test_ksm(folio)))rmap_walk_ksm(folio, rwc);else if (folio_test_anon(folio))rmap_walk_anon(folio, rwc, false);elsermap_walk_file(folio, rwc, false);
}

只看rmap_walk_anon

static 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);/* anon_vma disappear under us? */VM_BUG_ON_FOLIO(!anon_vma, folio);} else {
//从folio中获取anon_vmaanon_vma
= rmap_walk_anon_lock(folio, rwc);}if (!anon_vma)return;//page->index是page在file或内存区域中的偏移,单位是pagepgoff_start = folio_pgoff(folio);
//得到复合页的末尾indexpgoff_end
= pgoff_start + folio_nr_pages(folio) - 1;
//遍历avcanon_vma_interval_tree_foreach(avc,
&anon_vma->rb_root,pgoff_start, pgoff_end) {struct vm_area_struct *vma = avc->vma;
//得到page的虚拟地址unsigned
long address = vma_address(&folio->page, vma);VM_BUG_ON_VMA(address == -EFAULT, vma);cond_resched();if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg))continue;//使用回调函数rmap_one断开虚拟地址对应的pteif (!rwc->rmap_one(folio, vma, address, rwc->arg))break;if (rwc->done && rwc->done(folio))break;}if (!locked)anon_vma_unlock_read(anon_vma); }

rmap_walk_anon遍历anon_vma对应的rbtree,找到所有映射该页的vma,然后断开物理页对应虚拟地址的pte。

这里要理解page->index和vma->pgoff和vma->vm_start的关系。

由上图可以看到page->index指的是在整个文件或者进程地址空间(不一定是vma)上的偏移,要想得到它在当前vma内的偏移公式是vma->vm_start + (page->index - vma->vm_pgoff) << PAGE_SHIFT.

 

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

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

相关文章

一文了解Spark引擎的优势及应用场景

Spark引擎诞生的背景 Spark的发展历程可以追溯到2009年,由加州大学伯克利分校的AMPLab研究团队发起。成为Apache软件基金会的孵化项目后,于2012年发布了第一个稳定版本。以下是Spark的主要发展里程碑:初始版本发布:2010年开发的Matei Zaharia的研究项目成为Spark的前身。在…

Charles抓包工具

一.Charles介绍、安装、汉化 跨平台的抓包工具:Windows、linux、mac 它是基于http、https协议的道代理服务器 官网:https://www.charlesproxy.com/latest-release/download.do 特点:半免费 可以破解和汉化,仅供学习 优点: 1.支持按照域名查看、按接口列表的方式 2.弱网测试…

如何快速批量申请SSL证书

假如您手头拥有1千个域名,并且打算为每一个域名搭建网站,那么在当前的网络环境下,您必须确保这些网站通过https的方式提供服务。这意味着,您将为每一个域名申请SSL证书,以确保网站数据传输的安全性和可信度。那么,您该如何着手申请这些SSL证书呢? 一、一般方案 1、国内云…

SoftReference 到底在什么时候被回收 ? 如何量化内存不足 ?

本文基于 OpenJDK17 进行讨论,垃圾回收器为 ZGC。提示: 为了方便大家索引,特将在上篇文章 《以 ZGC 为例,谈一谈 JVM 是如何实现 Reference 语义的》 中讨论的众多主题独立出来。大家在网上或者在其他讲解 JVM 的书籍中多多少少会看到这样一段关于 SoftReference 的描述 —…

spring-2-依赖注入、循环依赖、三级缓存

参考: SpringBoot———自动装配原理 Spring 依赖注入有几种?各有什么优缺点? Spring注解@Resource和@Autowired区别 Spring是如何解决循环依赖问题? 第二次讲Spring循环依赖,时长16分钟,我保证每一秒都是精华 1.依赖注入 1.1 依赖注入的方式方式 优点 缺点 适用场景属…

FreeRTOS简单内核实现3 任务管理

简单实现了RTOS中非常重要的任务管理,可以成功启动第一个任务和切换任务,但仍然不支持并行运行效果0、思考与回答 0.1、思考一 对于 Cotex-M4 内核的 MCU 在发生异常/中断时,哪些寄存器会自动入栈,哪些需要手动入栈? 会自动入栈的寄存器如下R0 - R3:通用寄存器 R12:通用…

零基础-零成本搭建个人博客-Hexo-基于windows10

下载 nodejs # 1、访问官网:https://nodejs.org/en - 下载LTS版本下载后安装下一步、选择安装路径即可、注意要选择add to path(这是npm下载包的路径)安装hexo 安装成功后在cmd中输入npm验证一下:按 Win+R 键、弹出后 输入 cmd创建workspace:需要安装hexo下载的nmp包 F:\…

低代码(Low-Code)

现如今,我们已全面迈入智能互联网时代,新的技术不断迭代问世,也代表着新的生产力不断深入我们的生活,同时也是开创未来最好的原动力。那就眼下而言,什么样的新技术才能真正解放IT生产力,加速社会数字化转型呢?without doubt!我认为是低代码(Low-Code)。 什么是低代码…