核心 04-内存管理 预计 30 分钟 kp-017

分页机制与页表:地址翻译与 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 节。

自测题

  1. 为什么需要多级页表?

答:48 位虚拟地址的线性页表需要巨量连续内存存放大量空项;多级页表对未使用的地址区域整棵省略,用按需生长的树换取稀疏空间的低成本。

  1. TLB 未命中的代价来自哪里?

答:需要逐级访问内存中的页表(x86-64 四级最多 4 次访存),成本为普通访问的数倍,故 TLB 命中率对性能敏感。

  1. 缺页异常何时触发?

答:PTE 有效位为 0(页不在内存/未分配)、或权限位不符(写只读页如 COW 页)时,MMU 暂停指令并陷入内核处理程序。

标签:#分页 #页表 #TLB #多级页表 #MMU