分页机制与页表:地址翻译与 TLB
分页把虚拟地址空间切成固定大小的页(page)、物理内存切成同样大小的帧(frame),由页表记录"虚拟页号 → 物理帧号"的映射,硬件 MMU 在每次内存访问时完成翻译,TLB 缓存翻译结果以维持速度。
一句话定义
分页把虚拟地址空间切成固定大小的页(page)、物理内存切成同样大小的帧(frame),由页表记录"虚拟页号 → 物理帧号"的映射,硬件 MMU 在每次内存访问时完成翻译,TLB 缓存翻译结果以维持速度。
为什么重要
这是全库机制密度最高的知识点:COW(kp-007)、缺页与置换(kp-018)、保护与 ASLR(kp-020)、虚拟化硬件辅助(kp-029)全部构建在"页表 + 权限位 + 缺页异常"这套机制上。看不懂本节,后面所有内存章节都会变成背诵。
前置知识
kp-016(虚拟/物理地址的区别);kp-002(MMU 与缓存层级)。
核心概念
- VPN 与 offset:虚拟地址高位是虚拟页号(VPN),低位是页内偏移,翻译只换 VPN 部分。
- 页表项(PTE):含物理帧号与标志位:有效位、读/写/执行权限、访问位、脏位。
- 多级页表:树状页表,未使用的地址区域整棵子树缺席,用线性开销换稀疏空间。
- TLB(translation lookaside buffer):MMU 内的翻译缓存,命中则零额外开销。
- 大页(huge page):2MB/1GB 页减少页表深度与 TLB 压力。
- TLB shootdown:改页表后通知其他核失效对应缓存的跨核操作。
原理与机制
以 4KB 页、48 位虚拟地址、x86-64 四级页表为例:
虚拟地址 48 位: [ PML4(9) | PDPT(9) | PD(9) | PT(9) | offset(12) ]
翻译流程:
1. CPU 生成虚拟地址
2. TLB 命中? -> 直接得到物理地址,结束 (快路径, ~1 周期)
3. TLB 未命中 -> MMU 硬件逐级走页表:
CR3 -> 读 PML4 项 -> 读 PDPT 项 -> 读 PD 项 -> 读 PT 项
(每次都是真实内存访问, 4 次访存!)
4. 得到物理帧号 + offset = 物理地址, 装入 TLB
5. PTE 有效位为 0 或权限不符 -> 触发缺页异常, 交内核处理 (kp-018)
两级权衡清晰可见:页大小——大页减少页表级数与 TLB 条目压力,但加剧内碎片与调剂粒度变粗;页表结构——线性页表 48 位地址空间需数百 GB 表项不可行,多级页表让"从未用过的区域"零成本,代价是未命中时的多次访存(现代 CPU 用硬件页表遍历器 + 大 TLB 缓解)。这也是数据库与大内存服务开启透明大页(THP)争议的根源:TLB 命中率上升 vs 内存碎片与回收延迟。
图示
TLB 命中率决定翻译成本 (EAT 模型):
EAT = 命中率 x TLB时间 + 未命中率 x (TLB时间 + 页表遍历时间)
命中率 99% 时几乎无感; 降至 95%, 平均成本翻数倍 -> 大页/局部性优化的动机
直观类比
页表像图书馆的书架索引(虚拟书号 → 实际库房位置),MMU 是拿着索引的管理员;TLB 是管理员手里的便利贴——最近查过的位置不用再翻索引本。多级页表是把厚索引拆成目录树:没被借阅过的分区整章留白,一页纸都不印。
实例或案例
getconf PAGE_SIZE # 4096,页大小
cat /sys/kernel/mm/transparent_hugepage/enabled # THP 状态
perf stat -e dTLB-load-misses,cycles ls > /dev/null # 观察TLB未命中
numastat -m # 大页统计(numactl 包)
高级实验:读取 /proc/self/pagemap 配合 mincore() 观察某虚拟区间哪些页真正驻留物理内存,可亲眼验证 kp-019 的惰性分配。
常见误区
- 认为页表在内存里所以每次访存都要查表:TLB 命中率通常 99% 以上,走全页表的是少数。
- 把页表当成每个进程独占所有层级:父子进程 COW 期间共享帧,内核映射在全进程间共享。
- 认为 4KB 页是永恒真理:大页是处理大内存工作集的正规军,不是玄学调优。
与其他知识点的关系
缺页异常是 kp-018 虚拟内存的触发器;COW 是 kp-007 fork 的实现基础;EPT/NPT 是 kp-029 中同一思想的虚拟化延伸。
延伸阅读
《操作系统导论》"Mechanism: Address Translation"全章;《深入理解计算机系统》9.3~9.4 节。
自测题
- 为什么需要多级页表?
答:48 位虚拟地址的线性页表需要巨量连续内存存放大量空项;多级页表对未使用的地址区域整棵省略,用按需生长的树换取稀疏空间的低成本。
- TLB 未命中的代价来自哪里?
答:需要逐级访问内存中的页表(x86-64 四级最多 4 次访存),成本为普通访问的数倍,故 TLB 命中率对性能敏感。
- 缺页异常何时触发?
答:PTE 有效位为 0(页不在内存/未分配)、或权限位不符(写只读页如 COW 页)时,MMU 暂停指令并陷入内核处理程序。