目录
初识 PageWalk 机制
PageWalk 通识知识
PGD(Page Global Directory)
P4D(Page 4th Directory)
PUD(Page Upper Directory)
PMD(Page Middle Directory)
PTE(Page Table Entry)
PGPROT(Page Table Attribute)
PageWalk 机制数据结构
PageWalk 机制源码解析
PageWalk 机制实践
PageWalk 机制使用
遍历内核空间虚拟内存页表
遍历用户空间虚拟内存页表
遍历用户空间整个 VMA 页表
遍历文件映射 PageCACHE 的页表
遍历用户空间 Anonymous 映射内存页表
遍历用户空间 File 映射内存页表
遍历用户空间 Hugetlbfs Hugepage 内存页表
遍历用户空间 Transport Hugepage 内存页表
遍历用户空间 MMIO 页表
遍历用户空间 RSVDMEM 页表
遍历内核空间 VMALLOC 映射内存页表
遍历内核空间永久映射内存页表
遍历内核空间线性映射内存页表
遍历内核空间临时映射内存页表
遍历内核空间 IOREMAP 映射的 MMIO
遍历映射 CMA 内存页表
遍历映射 DMA 内存页表
修改/更新页表
新增/填充/删除页表
PageWalk 应用场景
SMAPs 场景: /proc/pid/smaps
NUMA_MAPS 场景: /proc/pid/numa_maps
Pagemap 场景: /proc/pid/pagemap
Clear Reference 场景: /proc/pid/clear_refs
Madvise: MADV_COLD 场景
Madvise: MADV_PAGEOUT 场景
Madvise: MADV_FREE 场景
Madvise: MADV_WILLNEED 场景
MLOCK 场景
Case by Case
walk_page_test
__walk_page_range
walk_pmd_range
walk_pte_range
PageWalk 进阶研究
mmap_lock 问题
pte_entry 上锁问题
无锁访问页表研究
page_walk_action 功能
PageWalk 导致 Split THP 研究
PageWalk 通识知识
在 Linux 里,每个进程都包含独立连续的线性空间,该空间被划分成两部分,其中一部分是进程使用的空间称用户空间地址空间,其为进程运行提供了运行所需的内存; 另外一部分是内核使用的空间称为内核地址空间。进程的线性空间包含虚拟内存,虚拟内存只有建立了页表映射到物理内存上,那么进程才能使用这段虚拟内存,否则会引起页面故障.
PageWalk 机制: Linux 内核提供用于页表遍历和页表修改的机制,可以对用户空间的虚拟内存或者内核空间虚拟内存,进行页表查询和页表修改。在 Linux 中,其最新的内核支持 5 级页表,分别是 PGD(Page Global Directory) 页表、P4D(Page 4th Directory) 页表、PUD(Page Upper Directory) 页表、PMD(Page Middle Directory) 页表 和 PTE(Page Table) 页表。Linux 采用这 5 级页表屏蔽了不同架构硬件页表之间的差异,统一采用 Linux 5 级页表进行管理。PageWalk 机制就是建立在 Linux 5 级页表之上的页表查询和页表修改.
PageWalk 机制 实现很精简,其就是遍历每一级页表,首先检查对应的 Entry 是否为空,如果是空那么就是调用 hole 相关的回调; 反之页表不为空,那么就会 Entry 进行访问或者修改, 接下来确认是否继续遍历下一级页表,如果是那么进入下一级页表继续之前的操作; 如果不继续遍历下一级页表,那么此时刷新 TLB,使最新的页表 Entry 更新到 TLB 里,最终完成遍历。PageWalk 机制 提供了一个遍历页表的机制,然后调用者可以根据需要选择特定的页表.
PageWalk 数据结构
PageWalk 机制 提供了 struct mm_walk_ops 数据结构,其内包含很多回调函数,调用者需要在哪一级页表操作,那么就实现该数据结构的成员即可,例如需要修改 PMD 页表,那么只需实现该数据结构的 pmd_entry 成员即可,当 PageWalk 机制遍历到 PMD 页表时,就会调用 pmd_entry 成员指向的回调函数. 其他成员的含义是: