2. 物理内存与虚拟地址空间:MMU与页表机制、物理页框与虚拟页、缺页异常处理流程

现代操作系统通过虚拟内存技术,为每个进程提供独立的、连续的虚拟地址空间,而底层物理内存则被划分为固定大小的物理页框(Page Frame)。本章深入剖析从虚拟地址到物理地址的转换核心——MMU与页表机制,并详细拆解缺页异常(Page Fault)的完整处理流程,为后续KSM与透明大页(THP)的性能调优奠定坚实的硬件与内核基础。

2.1 物理页框与虚拟页

物理内存被内核划分为固定大小的物理页框(通常为4KB),而进程的虚拟地址空间则被划分为同样大小的虚拟页(Virtual Page)。映射关系由页表维护。

概念 定义 大小 管理主体
物理页框 物理内存的最小分配单元,是硬件可寻址的实际存储区域 通常 4KB(x86_64 默认) 内核伙伴系统(Buddy Allocator)
虚拟页 进程虚拟地址空间中的连续区域,可能映射到物理页框或磁盘交换空间 与物理页框大小一致(4KB) 内核内存管理(MM)
页框号(PFN) 物理页框的索引编号,物理地址右移 PAGE_SHIFT 位得到 — 硬件/内核
关键理解:虚拟页是进程视角的“内存”,物理页框是硬件视角的“内存”。一个虚拟页可以映射到不同的物理页框,也可以不映射(未分配或换出)。KSM 的核心工作就是合并内容相同的物理页框,从而节省物理内存。

2.2 MMU与页表机制

内存管理单元(MMU)是CPU内部的硬件模块,负责将虚拟地址(VA)转换为物理地址(PA)。转换过程依赖页表(Page Table)——一种由内核维护的多级数据结构。

2.2.1 多级页表结构(x86_64 4级页表)

为了节省页表占用的物理内存,x86_64 架构采用 4 级页表(PML4、PDPT、PD、PT)。虚拟地址被划分为多个位段,每段索引一级页表。

虚拟地址分解(48位,4级页表):
| 63–48 | 47–39 (9 bit) | 38–30 (9 bit) | 29–21 (9 bit) | 20–12 (9 bit) | 11–0 (12 bit) | |:---:|:---:|:---:|:---:|:---:|:---:| | 符号扩展 | PML4 索引 | PDPT 索引 | PD 索引 | PT 索引 | 页内偏移 |

转换过程:MMU 从 CR3 寄存器获取 PML4 基址,依次索引 4 级页表,最终找到物理页框基址,加上页内偏移得到物理地址。

图 2-1:x86_64 4级页表地址转换流程 虚拟地址 (48位): [符号扩展] [PML4(9)] [PDPT(9)] [PD(9)] [PT(9)] [偏移(12)] PML4 (CR3) PDPT PD PT 物理页框 物理地址 = 页框基址 + 偏移

2.2.2 页表项(PTE)标志位

每个页表项不仅包含物理页框号(PFN),还包含关键的权限和状态标志位,直接影响缺页异常和性能调优。

标志位 名称 含义 对调优的影响
P Present 页是否在物理内存中(0 表示缺页或换出) 缺页异常触发条件
R/W Read/Write 0 只读,1 可读写 写时复制(CoW)依赖此位
U/S User/Supervisor 0 仅内核可访问,1 用户态可访问 内核/用户空间隔离
A Accessed 硬件自动置位,表示页被访问过 KSM 扫描、页面回收策略
D Dirty 硬件自动置位,表示页被写过 换出时需写回磁盘
PS Page Size 1 表示大页(2MB/1GB) 透明大页(THP)启用标志
性能陷阱:TLB(Translation Lookaside Buffer)是 MMU 内部的页表缓存。当使用 4KB 小页时,TLB 覆盖范围有限;启用透明大页(2MB)可显著提高 TLB 命中率,但会增加内存碎片和回收延迟。这是后续 THP 调优的核心矛盾。

2.3 缺页异常处理流程

当 CPU 访问一个虚拟地址,MMU 在页表中查找对应的 PTE,如果 Present 位为 0,则触发缺页异常(Page Fault)。Linux 内核的缺页异常处理函数(do_page_fault)根据异常类型执行不同的处理路径。

2.3.1 缺页异常分类

类型 触发条件 内核处理动作 性能影响
主要缺页 页不在内存,需要从磁盘交换区(swap)读入 发起 I/O,进程睡眠等待 高延迟(毫秒级),严重影响性能
次要缺页 页不在内存,但物理页框已分配(如共享内存、匿名页首次访问) 快速建立映射,无需 I/O 低延迟(微秒级)
写时复制缺页 访问只读共享页并尝试写入 复制物理页框,更新 PTE 为可写 中等延迟,fork() 后常见
无效缺页 访问未映射的地址(段错误) 发送 SIGSEGV 信号 程序崩溃

2.3.2 缺页异常处理流程详解

以下流程图展示了从虚拟地址访问到缺页处理完成的完整路径:

图 2-2:缺页异常处理流程 CPU 访问虚拟地址 MMU 查找页表 (TLB 未命中) PTE.Present == 0? 否 是 正常访问 触发缺页异常 do_page_fault() 异常类型? 主要缺页 次要缺页 写时复制 从 Swap 读入物理页框 分配/映射物理页框 复制页框,更新 PTE 更新 PTE,返回用户态

2.3.3 缺页异常与性能调优的关联

  • 主要缺页(Major Page Fault):是性能杀手,应极力避免。频繁的主要缺页意味着物理内存不足,系统正在大量使用交换空间。此时应考虑增加物理内存或优化内存占用(如启用 KSM 合并重复页)。
  • 次要缺页(Minor Page Fault):开销较小,但大量发生仍会增加内核路径开销。透明大页(THP)通过减少页表项数量,可降低次要缺页的频率。
  • 写时复制缺页(CoW Page Fault):在 fork() 后大量出现。KSM 的合并操作会触发 CoW,导致短暂性能下降,需要在内存节省和 CPU 开销之间权衡。
调优观察点:使用 sar -B 或 /proc/vmstat 监控 pgfault、pgmajfault、pgsteal_kswapd 等指标。如果 pgmajfault 持续不为 0,说明内存存在压力,KSM 或 THP 的调优可能带来收益。

2.4 本章小结

  • 物理页框是硬件分配单元,虚拟页是进程视角的抽象,二者通过页表建立映射。
  • MMU 负责硬件地址转换,多级页表在 x86_64 上节省了页表占用的物理内存。
  • 缺页异常分为主要缺页、次要缺页和写时复制缺页,内核根据 PTE 标志位和 VMA 属性执行不同的处理路径。
  • 理解缺页异常的分类和开销,是后续调优 KSM(减少物理页框数量)和 THP(增大映射粒度)的基础。