1. 内存管理基础:物理地址与虚拟地址的概念、MMU的作用、页表的基本结构

内存管理是操作系统内核最核心的子系统之一,而缺页异常(Page Fault)正是虚拟内存机制与物理内存管理之间的关键交互点。要深入理解缺页异常处理流程,必须先掌握三个基础概念:物理地址与虚拟地址、内存管理单元(MMU)以及页表。

1.1 物理地址与虚拟地址

物理地址(Physical Address, PA) 是硬件总线上的真实地址,直接对应内存芯片中的存储单元。CPU通过物理地址总线访问内存条上的数据。每个物理地址唯一标识一个字节的存储位置。

虚拟地址(Virtual Address, VA) 是程序视角看到的地址空间。每个进程拥有独立的虚拟地址空间(例如 32 位系统为 4GB,64 位系统更大),程序指令中使用的地址都是虚拟地址。虚拟地址必须经过转换才能变成物理地址。

核心认知: 虚拟地址是“假”的,物理地址是“真”的。进程永远活在虚拟世界里,MMU 负责把虚拟世界映射到物理现实。
对比维度 物理地址 虚拟地址
生成者 硬件总线 / 内存控制器 CPU 指令 / 程序逻辑
空间大小 由物理内存容量决定(如 4GB) 由 CPU 位宽决定(如 64 位为 16EB)
进程隔离 全局共享,无隔离 每个进程独立,天然隔离
程序可见性 用户态程序不可见 用户态程序直接使用
连续性 物理上可能不连续(碎片) 虚拟上连续,底层可离散
虚拟地址 → 物理地址转换概念图 进程 A 虚拟地址空间 0x0000_0000 代码段 数据段 堆 栈 0xFFFF_FFFF MMU 地址转换 (查页表) 虚拟地址 物理地址 物理内存 页框 0 页框 1 页框 2 页框 3 页框 4 页框 5 ... 虚拟地址连续,物理地址可以离散分布;MMU 通过页表完成映射

1.2 内存管理单元(MMU)的作用

MMU(Memory Management Unit) 是 CPU 内部的一个硬件模块,负责将虚拟地址实时转换为物理地址。它位于 CPU 核心与内存总线之间,是虚拟内存机制的硬件基石。

MMU 的核心职责

  • 地址转换: 将 CPU 发出的虚拟地址,通过查页表转换为物理地址。
  • 权限检查: 检查当前访问是否合法(读/写/执行权限、用户态/内核态权限)。
  • 缺页触发: 当页表项无效(页不在物理内存中)时,MMU 触发缺页异常(Page Fault),交由内核处理。
  • TLB 管理: 维护快表(Translation Lookaside Buffer),加速地址转换。
关键理解: MMU 是硬件加速器,页表是数据结构。MMU 每次访问内存都要查页表,TLB 缓存最近使用的页表项以减少性能开销。缺页异常是 MMU 发现页表项无效时向操作系统发出的“求救信号”。
MMU 在 CPU 内部的位置与工作流程 CPU 核心 发出虚拟地址 VA MMU ① 查页表 ② 权限检查 ③ 缺页判断 TLB 快表 PA 物理内存 数据读写 缺页异常 → 内核处理 MMU 是硬件引擎,页表是软件数据结构;MMU 查页表失败时触发缺页异常,操作系统接管

1.3 页表的基本结构

页表(Page Table) 是操作系统维护的一种数据结构,用于记录虚拟页号(VPN)到物理页框号(PFN)的映射关系。每个进程拥有独立的页表,存储在物理内存中,由 MMU 硬件直接读取。

页表项(PTE)的核心字段

每个页表项(Page Table Entry, PTE)通常包含以下关键信息:

字段 位宽(典型) 说明
物理页框号(PFN) 20-52 位 映射到的物理内存页框起始地址
Present 位(P) 1 位 页是否在物理内存中(0 表示缺页)
Read/Write 位(R/W) 1 位 是否允许写入(0 为只读)
User/Supervisor 位(U/S) 1 位 用户态是否可访问(0 仅内核态)
Accessed 位(A) 1 位 页是否被访问过(用于页面置换)
Dirty 位(D) 1 位 页是否被写入过(用于回写)

多级页表结构(以 x86_64 为例)

现代 64 位系统使用多级页表来节省内存。以 Linux 内核在 x86_64 架构上的 4 级页表为例:

  1. PGD(Page Global Directory) — 全局页目录
  2. P4D(Page 4th Directory) — 第 4 级页目录(某些配置下省略)
  3. PUD(Page Upper Directory) — 上层页目录
  4. PMD(Page Middle Directory) — 中间页目录
  5. PTE(Page Table Entry) — 页表项
注意: 多级页表的核心优势在于:对于大地址空间中未使用的部分,可以不为它们分配页表中间节点,从而大幅节省内存。缺页异常发生时,内核需要逐级遍历页表,找到或创建对应的页表项。
x86_64 四级页表地址转换流程 虚拟地址:63位 ─────────────────────────────────────────── 0位 PGD 索引 PUD 索引 PMD 索引 PTE 索引 页内偏移(12位) PGD PUD PMD PTE 物理页框 + 页内偏移 每级页表存储下一级页表的物理地址;PTE 中存储最终的物理页框号;页内偏移直接拼接

1.4 地址转换与缺页的触发条件

当 CPU 执行指令访问某个虚拟地址时,MMU 执行以下步骤:

  1. TLB 查找: 先在 TLB 中查找是否有该虚拟地址的转换缓存。如果命中(TLB hit),直接得到物理地址。
  2. 页表遍历: TLB 未命中(TLB miss)时,MMU 硬件自动遍历多级页表,逐级读取页表项。
  3. 权限检查: 检查 PTE 中的 U/S 位、R/W 位是否允许当前访问。
  4. Present 位判断: 检查 PTE 的 Present 位是否为 1。
    • 若 Present=1:页在物理内存中,MMU 取出 PFN,拼接页内偏移,生成物理地址,访问内存。
    • 若 Present=0:页不在物理内存中,MMU 触发 缺页异常(Page Fault),CPU 切换到内核态,执行缺页异常处理程序。
缺页异常的本质: 缺页异常不是错误,而是虚拟内存系统的正常工作机制。当进程访问的虚拟页尚未加载到物理内存、已被换出到磁盘、或是首次访问的匿名页时,MMU 通过缺页异常通知内核去“补上”这个页。内核在缺页处理中完成物理页分配、磁盘 I/O 读取、页表项填充等操作。
MMU 地址转换与缺页触发决策流程 CPU 发出虚拟地址 TLB 查找 TLB 命中 → 直接访问 TLB 未命中 → 查页表 检查 PTE.Present 位 Present=1 → 正常访问;Present=0 → MMU 触发缺页异常,内核接管

1.5 本章小结

  • 物理地址 是硬件真实地址,虚拟地址 是进程视角的地址,两者通过 MMU 转换。
  • MMU 是 CPU 内部的硬件单元,负责地址转换、权限检查和缺页触发。
  • 页表 是存储在内存中的多级数据结构,每个进程独立拥有,页表项包含 PFN、Present 位、权限位等关键字段。
  • 当页表项的 Present 位为 0 时,MMU 触发缺页异常,这是后续章节要深入分析的核心机制。