欢迎光临散文网 会员登陆 & 注册

一篇看懂|Linux内核反向映射机制原理

2022-11-01 20:13 作者:补给站Linux内核  | 我要投稿

当内核需要对申请的page进行回收时,在回收页表前需要解除该page的映射关系,即内核需要知道这个物理页被映射到了哪些进程虚拟地址空间,因此就有了反向映射机制。反向映射一般分为匿名页映射和文件页映射,本文先介绍匿名页反向映射。

基本数据结构

page结构体中涉及反向映射的相关成员

  • mapping 因为指针变量是4个字节,因此可以用最后两位来区分不同的映射。对于匿名映射,最低位为PAGE_MAPPING_ANON,指向anon_vma结构体,每个匿名页对应唯一的anon_vma;对于文件映射而言,指向address_space结构体。

  • index表示页偏移,对于匿名映射,index 表示page在vm_areat_struct指定的虚拟内存区域中的页偏移;对于匿名映射,index表示物理页中的数据在文件中的页偏移。

  • _mapcount 记录该页面被映射到了多少个vm_struct虚拟内存区域。注意和mm_struct结构体中的map_count做区分,map_count表示mm_strcut中有多少个vm_struct区域。

一般struct anon_vma称为AV,struct anon_vma_chain称为AVC,struct vm_area_struct称为VMA,page找到VMA的路径一般如下:page->AV->AVC->VMA,其中AVC起到桥梁作用,至于为何需要AVC,主要考虑当父进程和多个子进程同时拥有共同的page时的查询效率,具体对比2.6版本时的实现方式。

结构anon_vma

结构anon_vma_chain

struct vm_struct中相关成员

上面几个结构体的关系大致如下:


page通过mapping找到VMA,VMA 遍历自己管理的红黑树rb_root,找到树上的每个节点AVC,AVC通过成员指针anon_vma找到对应的VMA,这个过程就完成了页表映射查找。需要注意的几点:

1.VMA中也有链表anon_vma_chain管理各个AVC,这里主要用在父子进程之间的管理,下文会详细介绍。

2.VMA中有成员指针成员anon_vma,同时AVC中也有成员指针anon_vma,VAC起到桥梁作用所以可以指向VMA和AVC,那VMA中为何又需要指向AV呢?进程创建的流程中一般都是新建AV,然后创建AVC及AMV,然后调用anon_vma_chain_link建立三者之间的关系,但是当一个VMA没有对应页的时候,此时触发pagefault,这里可以快速判断VMA有没有对应的页面。


【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!(含视频教程、电子书、实战项目及代码)   


常用接口

  • anon_vma_chain_link 1.将VAC中的vma和anon_vma分别指向VMA和AV; 2.将AVC加入到VMA的anon_vma_chain链表上; 3.将AVC加入到AV的rb_root红黑树上,通常都是通过遍历这个红黑树找到所有的AVC;

代码实现

反向映射跟父子进程的写时拷贝有关系,所以先从父子进程创建时对AV,AVC,VMA的创建开始讲。

1.父进程创建匿名页面


当触发pagefault的时候走到handle_pte_fault中,anon_vma_prepare中负责创建AVC和AV并建立彼此的关系;真正将创建的page与av关联在__page_set_anon_map中完成。这样的话父进程新建的page在自己的反向映射中的关系就算完成了。

至于index的含义看linear_page_index的实现应该就明白了。

2.父进程创建子进程

当父进程创建子进程的时候,子进程会复制父进程的VMA作为自己的进程地址空间,并且父子进程共享相同的页面,知道子进程往自己的地址空间写数据,这就是所谓的COW。这种情况需要完成两件事情:1.子进程需要继承父进程的AVC,AV,VMA及三者之间的关系;2.创建自己的AV,AVC,VMA。

以上实现流程在dup_mm->dup_mmap->anon_vma_fork中完成。

dup_mmap中就是组个创建子进程的VMA,并复制父进程对应VMA的信息



anon_vma_clone中新建了AVC,将子进程的VMA关联到父进程的AV中,所以父进程AV的rb树上就有了子进程的AVC,通过遍历父进程AV的rb树就能找到子进程的VMA。一个VMA可以包含多个页面,但是该区域内的所有页面只需要一个AV来反向映射即可。


具体anon_vma_clone代码如下

3.子进程发生cow,创建自己的匿名页面

当新创建的子进程写数据时触发pagefault,在wp_page_copy中会创建新的page,此时创建的AV和AVC管理子进程自己的VMA

4.页面回收,解除映射

物理页回收时通过调用try_to_unmap解除一个page的页表映射。对于匿名页面解除映射而言,走

try_to_unmap->rmap_walk->rmap_walk_anon流程。

rmap_one指向try_to_umap_one,该函数内容比较复杂,这里只截取了页表项解除的操作。

原文作者:Linux内核那些事

一篇看懂|Linux内核反向映射机制原理的评论 (共 条)

分享到微博请遵守国家法律