Linux内存管理:struct page到vma列表的反向映射实现咨询
Linux 页帧到VMA列表的反向映射实现
核心区分:匿名页 vs 文件映射页
反向映射(RMAP)的实现分两种核心场景,差异源于页的来源类型:
1. 匿名页的反向映射(依赖anon_vma)
你在旧书中了解的anon_vma关联逻辑,在现代内核里有字段结构的优化调整:
- 早期内核的
struct page确实有直接的anon_vma指针,但为了节省内存空间,后续改成复用page->mapping字段:- 当
page->mapping的最低两位为PAGE_MAPPING_ANON标志时,剥离标志位后的指针实际指向struct anon_vma结构。 struct anon_vma内部通过红黑树(rb_root)维护struct anon_vma_chain节点列表,每个anon_vma_chain直接关联对应的struct vm_area_struct(VMA)。
- 当
- 遍历路径:从
struct page拿到anon_vma→ 遍历红黑树中的anon_vma_chain节点 → 每个节点对应一个VMA → 进一步定位到该VMA所属进程的页表及目标PTE。
2. 文件映射页的反向映射
对于文件-backed的页,page->mapping直接指向文件inode对应的struct address_space结构。address_space通过i_mmap红黑树(受i_mmap_rwsem保护)管理所有映射该文件页的VMA,遍历此红黑树即可获取所有关联的VMA,进而找到对应的PTE。
修改PTE时的反向映射处理流程
当需要修改目标页帧对应的PTE时,大致步骤如下:
- 通过
struct page判断页类型(匿名/文件映射),获取对应的VMA列表。 - 对每个关联的VMA,遍历其所属进程的页表,定位到具体的PTE项。
- 调用
ptep_clear_flush这类函数清除PTE映射,并刷新TLB。 - 根据场景更新页的状态(如标记脏页、调整引用计数等)。
旧书与现代内核的差异
你阅读的《Understanding the Linux Virtual Memory Manager》和《Understanding the Linux Kernel》基于2.4/2.6早期内核,现代内核(3.x及以后)对反向映射做了不少优化:
- 复用
struct page字段以降低内存开销。 - 引入
anon_vma_chain优化多进程共享匿名页(如fork后的写时复制场景)的遍历效率。 - 文件映射的RMAP用红黑树替代了早期的链表实现,提升了查找性能。
内容的提问来源于stack exchange,提问作者Rohit
相关产品推荐
相关产品推荐

