Linux内核MMU x86分页模式与4级页表实战 - 第1节
1.1 MMU 的核心作用
内存管理单元(Memory Management Unit, MMU)是 CPU 内部负责虚拟地址到物理地址转换的硬件模块。在 x86 架构中,MMU 位于 CPU 核与内存控制器之间,是操作系统实现进程隔离、虚拟内存、按需分页的核心硬件基础。
MMU 三大核心职责:
- 地址转换:将程序使用的虚拟地址(VA)转换为内存芯片上的物理地址(PA)。
- 内存保护:通过页表项的权限位(读/写/执行/用户/内核)阻止非法访问。
- 缓存控制:管理 TLB(Translation Lookaside Buffer)和页表缓存,加速地址转换。
1.2 虚拟地址与物理地址
1.2.1 基本概念
| 地址类型 | 定义 | 特点 | 示例(x86-64) |
|---|---|---|---|
| 虚拟地址(VA) | 程序指令中使用的地址,由 CPU 生成 | 每个进程拥有独立的 48 位虚拟地址空间(当前实现) | 0x7ffeefbff5a0 |
| 物理地址(PA) | 内存芯片上的真实地址,由 MMU 输出 | 受物理内存容量限制,x86-64 支持最多 52 位 | 0x0000000123456789 |
| 线性地址(LA) | x86 分段机制转换后的地址,MMU 的输入 | 现代 Linux 中 LA = VA(分段被扁平化) | 同 VA |
关键理解: 在 Linux 内核中,每个用户态进程看到的是从 0x0000000000000000 到 0x00007fffffffffff 的 128TB 虚拟地址空间,而内核映射在 0xffff800000000000 以上的高地址区域。这些虚拟地址通过 MMU 的页表机制映射到物理内存的不同位置。
1.2.2 地址转换的数学本质
MMU 将虚拟地址划分为页号(VPN)和页内偏移(Offset)两部分。页号通过页表查找得到物理页号(PPN),然后拼接偏移得到物理地址:
虚拟地址 (48 bits):
+---------------------+------------------+
| 页号 (VPN) | 页内偏移 |
| 36 bits | 12 bits |
+---------------------+------------------+
物理地址 (48 bits):
+---------------------+------------------+
| 物理页号 (PPN) | 页内偏移 |
| 36 bits | 12 bits |
+---------------------+------------------+
转换公式: PA = (PPN << 12) | Offset
其中 PPN = PageTable[VPN]
1.3 内存管理单元的基本原理
1.3.1 页式内存管理
MMU 采用分页(Paging)机制管理内存。物理内存被划分为固定大小的页框(Page Frame),虚拟内存被划分为相同大小的页(Page)。x86 架构支持多种页大小:
| 页大小 | 偏移位数 | 适用场景 | TLB 覆盖范围 |
|---|---|---|---|
| 4 KB | 12 bits | 标准页,通用场景 | 较小 |
| 2 MB | 21 bits | 大页(HugePage),数据库/虚拟化 | 较大 |
| 1 GB | 30 bits | 超大页,HPC/内存密集型 | 极大 |
1.3.2 页表与多级转换
x86-64 架构使用4 级页表结构(PML4 → PDPT → PD → PT),每级页表包含 512 个 8 字节的页表项(PTE)。这种多级设计的好处是:
- 节省内存:只有实际使用的虚拟地址范围才需要分配页表。
- 支持稀疏地址空间:进程通常只使用虚拟地址空间的一小部分。
- 共享页表:内核空间页表可以在所有进程间共享。
性能关键点: 每次地址转换最多需要 4 次内存访问(4 级页表遍历)。TLB 缓存最近使用的转换结果,命中率通常超过 99%。当 TLB 未命中时,MMU 硬件自动执行页表遍历(硬件页表遍历,x86 从 Penryn 微架构开始支持)。
1.3.3 内存保护与权限控制
每个页表项(PTE)包含权限位,MMU 在地址转换的同时检查访问合法性:
| 权限位 | 含义 | 违规后果 |
|---|---|---|
| R/W | 读/写权限(0=只读,1=读写) | 写只读页 → #PF(页错误) |
| U/S | 用户/超级用户(0=内核,1=用户) | 用户态访问内核页 → #PF |
| NX | 不可执行(1=禁止执行代码) | 在 NX 页上执行 → #PF |
| Present | 页是否在物理内存中(0=缺页) | 访问不存在的页 → #PF(触发换入) |
1.3.4 TLB 与转换加速
TLB(Translation Lookaside Buffer)是 MMU 内部的硬件缓存,存储最近使用的虚拟页号到物理页号的映射。TLB 的典型特征:
- 容量:L1 TLB 通常 64~64 项,L2 TLB 512~2048 项。
- 层级:分离的指令 TLB(ITLB)和数据 TLB(DTLB)。
- 关联度:全相联或组相联,减少冲突未命中。
- 刷新:进程切换时需刷新 TLB(或使用 PCID 标记避免刷新)。
TLB 命中 vs 未命中性能对比:
- TLB 命中:约 1~2 个 CPU 周期,几乎无延迟。
- TLB 未命中 + 硬件页表遍历:约 10~100 个周期(取决于页表层级和缓存命中情况)。
- TLB 未命中 + 缺页处理:数千到数百万个周期(涉及磁盘 I/O)。
1.4 本章小结
| 知识点 | 核心要点 |
|---|---|
| MMU 作用 | 地址转换、内存保护、缓存控制 |
| 虚拟地址 vs 物理地址 | VA 是程序视角,PA 是硬件视角,MMU 桥接两者 |
| 分页机制 | 固定大小页框,4KB/2MB/1GB 可选 |
| 4 级页表 | PML4 → PDPT → PD → PT,每级 512 项 |
| TLB | 硬件缓存加速转换,进程切换需刷新 |
| 权限控制 | R/W、U/S、NX、Present 位实现保护 |