3、内存管理单元(MMU)基础:MMU的作用、虚拟地址到物理地址的转换流程

内存管理单元(Memory Management Unit, MMU)是处理器内部负责地址转换与内存保护的关键硬件模块。它位于CPU核心与内存控制器之间,是操作系统实现虚拟内存、进程隔离与内存保护的物理基础。理解MMU的工作原理,是掌握现代内存管理体系的起点。

3.1 MMU的核心作用

MMU在计算机体系结构中承担以下三项核心职责:

职责 说明 对操作系统的影响
地址转换 将CPU发出的虚拟地址(VA)转换为物理地址(PA) 支持虚拟内存空间,每个进程拥有独立的地址空间
内存保护 检查访问权限(读/写/执行)、特权级(用户/内核) 防止进程越界访问,保障系统安全
缓存控制 管理TLB(转译后备缓冲器)与Cache的协同 提升内存访问效率,降低平均访问延迟
关键认知: 没有MMU,操作系统只能使用物理地址直接编程,无法实现进程隔离、虚拟内存、按需分页等现代OS核心功能。MMU是“虚拟化”思想在内存管理中的硬件体现。

3.2 虚拟地址到物理地址的转换流程

当CPU执行一条访问内存的指令(如 LOAD R1, [0x00401000])时,MMU介入完成以下步骤:

  1. CPU发出虚拟地址:程序计数器或访存指令生成一个虚拟地址(VA)。
  2. TLB查找:MMU首先在TLB中查找该虚拟地址对应的页表项(PTE)。如果命中(TLB Hit),直接获得物理地址。
  3. 页表遍历(TLB Miss时):若TLB未命中,MMU硬件自动遍历多级页表,从内存中读取页表项。
  4. 权限检查:MMU检查页表项中的权限位(R/W/X、User/Supervisor),若违反则触发缺页异常或保护异常。
  5. 物理地址生成:将虚拟页号(VPN)转换为物理页号(PPN),与页内偏移(Offset)拼接得到完整物理地址。
  6. 访问物理内存:物理地址被发送到内存控制器,完成数据读取或写入。
性能提示: TLB命中率通常超过99%。当发生TLB Miss时,硬件页表遍历需要多次内存访问(4级页表需要4次),这是影响内存访问延迟的关键因素。

3.3 地址转换的数学结构

以典型的4KB页大小、48位虚拟地址空间为例,地址拆分如下:

虚拟地址(48位):
+----------------+----------------+----------------+----------------+--------------+
|  VPN[3] (9位)  |  VPN[2] (9位)  |  VPN[1] (9位)  |  VPN[0] (9位)  |  Offset(12位) |
+----------------+----------------+----------------+----------------+--------------+
  页全局目录       页上级目录       页中间目录       页表项          页内偏移

物理地址(48位):
+----------------+--------------+
|   PPN (36位)   |  Offset(12位) |
+----------------+--------------+

转换公式:

  • 虚拟页号(VPN) = VA >> 12(右移12位去掉页内偏移)
  • 物理地址(PA) = (PPN << 12) | Offset
  • 页表项大小:通常为8字节(64位架构),包含物理页号、权限位、存在位、脏位等。

3.4 多级页表转换流程(SVG架构图)

多级页表地址转换流程(x86-64 4级页表) CPU 虚拟地址 TLB 查找 物理地址输出 TLB Miss 硬件页表遍历(4级) PML4(第1级) PDPT(第2级) PD(第3级) PT(第4级) 页表项(PTE) 权限检查 缺页/保护异常 物理地址 转换流程说明: ① CPU发出48位虚拟地址,MMU提取VPN[3:0]和Offset。 ② TLB命中则直接输出物理地址,无需访问内存页表。 ③ TLB未命中时,硬件遍历4级页表,每级从内存读取页表项。 ④ 最终PTE提供物理页号,与Offset拼接得到物理地址。

3.5 TLB与页表缓存的协同

TLB作为页表项的硬件缓存,其结构与操作直接影响系统性能:

特性 TLB 页表(内存中)
存储位置 CPU芯片内部(SRAM) 主存(DRAM)
访问延迟 1~2个CPU周期 数十到数百个周期
容量 通常32~2048个条目 可占用GB级内存
替换策略 LRU或伪LRU(硬件实现) 由操作系统管理
一致性维护 需要TLB shootdown(多核) 页表修改后需刷新TLB
多核陷阱: 当操作系统修改某个进程的页表项(如换出页面)时,必须确保所有CPU核上的TLB中对应的旧条目被无效化。这一过程称为TLB Shootdown,是操作系统内核中开销较大的同步操作之一。

3.6 地址转换中的异常处理

MMU在转换过程中可能触发以下异常,由操作系统内核负责处理:

  • 缺页异常(Page Fault):页表项的存在位为0,表示该虚拟页未映射到物理页。操作系统从磁盘交换区加载数据到物理内存,更新页表后重新执行指令。
  • 保护异常(Protection Fault):访问权限不匹配(如用户态写只读页、内核态访问用户页但未设置Supervisor位)。操作系统通常向进程发送SIGSEGV信号。
  • TLB Miss异常(少数架构):部分精简指令集(RISC)架构将TLB Miss处理交给软件,由操作系统遍历页表并填充TLB。
性能权衡: 硬件页表遍历(x86/ARM)与软件TLB Miss处理(MIPS/SPARC)各有优劣。硬件遍历减少异常开销但增加芯片复杂度;软件处理更灵活但TLB Miss延迟更高。现代主流架构均采用硬件页表遍历。

3.7 大页(Huge Pages)与MMU

为减少TLB Miss并提升大内存工作负载的性能,MMU支持多种页大小:

页大小 典型架构 TLB覆盖范围(64条目) 适用场景
4 KB 所有架构默认 256 KB 通用、小内存分配
2 MB x86-64、ARMv8 128 MB 数据库、JVM堆、大页缓存
1 GB x86-64(PDPE级) 64 GB 虚拟化、高性能计算

使用大页时,MMU只需一级或两级页表遍历即可完成转换,大幅减少页表层级和TLB压力。操作系统通过 madvise() 或透明大页(THP)机制为应用程序启用大页支持。

// 使用 mmap 分配 2MB 大页(Linux)
#include <sys/mman.h>
#include <fcntl.h>

#define HUGE_PAGE_SIZE (2 * 1024 * 1024)  // 2MB

void *addr = mmap(NULL, HUGE_PAGE_SIZE,
                  PROT_READ | PROT_WRITE,
                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
                  -1, 0);
if (addr == MAP_FAILED) {
    perror("mmap huge page failed");
    // 回退到普通 4KB 页
}
实践建议: 对于内存密集型应用(如Redis、PostgreSQL、Java应用),启用大页可降低TLB Miss率15%~30%,显著提升吞吐量。但大页会导致内存碎片化,需根据工作负载特征权衡。

3.8 本章小结