谷动谷力

 找回密码
 立即注册
查看: 1886|回复: 0
打印 上一主题 下一主题
收起左侧

反向映射rmap

[复制链接]
跳转到指定楼层
楼主
发表于 2023-10-30 20:17:54 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
反向映射rmap


在内存回收时,除了将物理页还给伙伴系统,还需要解除物理页和虚拟页面的映射关系。

从 物理地址找对应的虚拟地址,就是反向映射。匿名页、ksm页面和文件页面,它们的反向映射机制不一样。
这一节简单了解下这三种反向映射。内核版本linux-5.15.60。

一、匿名页的反向映射

一个物理匿名页面可以同时被多个进程的虚拟地址内存映射,但一个虚拟页面只能有一个物理匿名页面与之映射。

不同虚拟页面同时映射到同一物理匿名页面是因为子进程克隆父进程VMA,和KSM机制的存在。

当发生匿名页缺页异常时,进程会向系统申请一个物理页 struct page, 每个page 有一个 struct anon_vma *anon_vma与之对应,它的成员 struct rb_root_cached rb_root会用一颗间隔树(底层为红黑树)保存此物理页映射的所有虚拟地址空间。

对于一个物理页的每个虚拟地址空间,用结构体 struct anon_vma_chain *avc 表示,一方面avc 链接到 anon_vma 的间隔树中;另一方面,avc 链接到 vma的双向链表中。

因此,当发生缺页异常,创建匿名页面page01 后,系统会建立下图的[page01, av01, avc01, vma00]的关系。
(函数实现在:do_anonymous_page ->  anon_vma_prepare ->  __anon_vma_prepare )

注意,在分配 struct anon_vma 之前,内核会检查相邻的vmas 是否存在合适的anon_vma,有的话,则会复用anon_vma。
子进程创建时,会复制父进程的 vma,因此,同一个物理页,在父子进程当中的虚拟地址是一样的。

子进程在fork时,会遍历父进程的 anon_vma_chain,并创建 N个 avc,并将 avc 链接到物理页的间隔树中。如上图的 [vma10, avc10].
(函数实现在:kernel_clone->copy_process->copy_mm->dup_mm->dup_mmap->anon_vma_fork ->  anon_vma_clone)
要解除某个匿名物理页的映射关系,得知道两点信息,一是有哪些 vmas 映射了,二是这些 vmas 的虚拟地址。

对于第一点,从前面的描述可以得知,通过page->  anon_vma->间隔树 就能找到所有的 vmas。

关键是第二点,同一个物理页在多个父子进程的虚拟地址是一样,因此,内核使用page->index 来保存物理页的虚拟页号。

通过vma ->mm_struct->pgd 。通过pgd 和 虚拟地址,就可以遍历页面得到pte,然后解除映射。
(函数实现在mm\rmap.c:page_referenced -> rmap_walk ->rmap_walk_anon)

二、KSM反向映射

KSM(kernel shared memory)是一种内存共享机制,启用 ksm后,ksm守护进程会定期扫描用户内存区域,并合并具有相同内存的匿名物理页面以减少页面的冗余。

和“多个子进程”不一样的是,映射到同一个物理页面, ksm 在不同进程的虚拟地址空间的虚拟地址肯定是不一样的,因此就不能使用 page->index 来表示虚拟页号。

对于ksm 页面,内核维护了一个结构体 rmap_item,用它来保存同一物理页面在不同的虚拟地址空间信息。

物理页的 mapping 指向了一个 struct stable_node 结构体,通过 stable_node->hlist 将 rmap_item 连接起来。
rmap_item中维护了page对应的虚拟地址address及anon_vma结构。
(函数实现:mm\rmap.c:page_referenced -> rmap_walk ->rmap_walk_ksm)

三、文件页的反向映射

对于文件页的反向映射,借用知乎兰大师的文章和图。
物理页的 mapping 会指向文件对应的 address_space,address_space 的i_mmap 保存了所有的vma。物理页的所有 vma,很容易找到,那不同vma的虚拟地址呢?

物理页的index 表示物理页在文件内的offset(以page size为单位),vma的vm_pgoff 表示 vma 区域在文件中的偏移量。那么,在不同的vma的虚拟地址= page->index - vma->vm_pgoff  + vma->vm_start 。
知道了 vma和 虚拟地址,就可以解除pte映射了。
(函数实现:mm\rmap.c:page_referenced -> rmap_walk ->rmap_walk_file)

参考:
https://www.cnblogs.com/ccxikka/p/10647294.html
https://zhuanlan.zhihu.com/p/68071761

+10
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-12-27 08:57 , Processed in 0.082943 second(s), 42 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表