1. 内存管理全景:Linux内存管理子系统概述、虚拟内存与物理内存、MMU与页表基础

1.1 Linux内存管理子系统全景

Linux内存管理子系统是内核中最复杂、最核心的模块之一,负责协调系统中所有内存资源的分配、回收与映射。它向上为进程提供独立的虚拟地址空间,向下管理物理内存页框,中间通过MMU与页表完成地址转换。

核心职责: 地址映射、内存分配/回收、页面换入换出、缺页异常处理、内存碎片整理、内存热插拔。

内存管理子系统的主要组件与层次关系如下表所示:

层次/组件 核心数据结构 主要功能
进程地址空间 mm_struct, vm_area_struct 管理进程虚拟内存布局(堆、栈、映射段)
虚拟内存映射 页表(Page Table) 虚拟地址 → 物理地址转换
物理内存管理 page, zone, pglist_data 物理页框分配与回收
分配器 伙伴系统(Buddy System) 连续物理页框分配,抗外部碎片
小块内存分配 SLUB/SLAB分配器 内核对象缓存,抗内部碎片
页面回收 LRU链表, kswapd 页面换出与内存压力调节
Linux 内存管理子系统架构 用户空间(User Space) 进程 A (mm_struct) | 进程 B (mm_struct) | 进程 C (mm_struct) 虚拟内存层(VMA + 页表) vm_area_struct 链表 | 页表(PGD/PUD/PMD/PTE) 物理内存管理层(Node / Zone / Page) pglist_data | zone (DMA/NORMAL/HIGHMEM) | struct page 内存分配器层 伙伴系统(Buddy) | SLUB分配器 | vmalloc 硬件层(MMU + 物理内存) TLB | 物理页框 | 内存控制器

1.2 虚拟内存与物理内存

虚拟内存是Linux为每个进程提供的独立、连续的地址空间抽象,而物理内存是硬件实际可寻址的RAM。两者通过页表建立映射关系。

关键概念: 虚拟地址(VA)由CPU生成,经过MMU转换为物理地址(PA)。进程只能看到虚拟地址,无法直接访问物理地址。

虚拟内存的核心优势:

  • 隔离性: 每个进程拥有独立的虚拟地址空间,互不干扰。
  • 安全性: 用户态进程无法访问内核空间。
  • 灵活性: 允许使用比物理内存更大的地址空间(通过换页)。
  • 简化编程: 程序员无需关心物理内存碎片和布局。

虚拟地址空间布局(以x86-64为例):

区域 起始地址 说明
代码段(.text) 0x400000 可执行指令
数据段(.data/.bss) 代码段之后 全局变量、静态变量
堆(Heap) 数据段之后 动态分配(brk/mmap)
内存映射段 堆与栈之间 共享库、mmap文件
栈(Stack) 高地址向下增长 局部变量、函数调用
内核空间 0xFFFF8000 00000000 内核代码与数据(用户态不可见)
虚拟内存 → 物理内存映射 虚拟地址空间 进程 A 栈 (0x7fff...) 堆 (0x6000...) 数据段 代码段 (0x4000...) 页表 VA→PA 映射 物理内存(RAM) 页框 0x1000 页框 0x2000 页框 0x3000 页框 0x4000 页框 0x5000 页框 0x6000 虚拟地址连续 物理地址可以不连续 通过页表映射

1.3 MMU与页表基础

内存管理单元(MMU)是CPU内部的硬件模块,负责将虚拟地址实时转换为物理地址。页表是存储在内存中的多级数据结构,MMU通过遍历页表完成地址转换。

性能关键: 每次内存访问都需要一次页表遍历(多级查表),TLB(Translation Lookaside Buffer)作为页表的硬件缓存,可以大幅加速地址转换。TLB miss会导致性能下降。

x86-64四级页表结构:

页表级别 缩写 索引位数 覆盖范围
页全局目录 PGD 9 bits 512 个 PMD 条目
页上级目录 PUD 9 bits 512 个 PMD 条目
页中间目录 PMD 9 bits 512 个 PTE 条目
页表条目 PTE 9 bits 512 个物理页框(4KB)

地址转换过程(x86-64,4KB页):

  1. CPU发出48位虚拟地址 VA[47:0]。
  2. MMU从控制寄存器 CR3 读取PGD基地址。
  3. 使用 VA[47:39] 作为PGD索引,找到PUD表地址。
  4. 使用 VA[38:30] 作为PUD索引,找到PMD表地址。
  5. 使用 VA[29:21] 作为PMD索引,找到PTE表地址。
  6. 使用 VA[20:12] 作为PTE索引,找到物理页框基地址。
  7. 物理地址 = 页框基地址 + VA[11:0](页内偏移)。
x86-64 四级页表地址转换流程 虚拟地址 (48 bits) [47:39] PGD索引 | [38:30] PUD索引 | [29:21] PMD索引 | [20:12] PTE索引 | [11:0] 页内偏移 CR3 (PGD基址) PGD 表 PUD 表 PMD 表 PTE 物理页框 基地址 + 偏移 地址转换步骤详解 ① CPU 发出 VA → MMU 从 CR3 读取 PGD 基址 ② 用 VA[47:39] 索引 PGD → 得到 PUD 表地址 ③ 用 VA[38:30] 索引 PUD → 得到 PMD 表地址 ④ 用 VA[29:21] 索引 PMD → 得到 PTE 表地址 ⑤ 用 VA[20:12] 索引 PTE → 得到物理页框基址 ⑥ 物理地址 = 页框基址 + VA[11:0](页内偏移)

1.4 页表条目(PTE)标志位

每个PTE不仅包含物理页框号(PFN),还包含一组标志位,用于控制页面的访问权限和状态。

标志位 含义 说明
P (Present) 页面是否在物理内存中 0表示缺页,触发缺页异常
R/W 读写权限 0只读,1可读写
U/S 用户/超级用户权限 0仅内核可访问,1用户态也可访问
A (Accessed) 页面是否被访问过 硬件自动置位,用于页面置换算法
D (Dirty) 页面是否被写入过 硬件自动置位,用于回写判断
NX (No-Execute) 禁止执行 防止代码段被篡改执行
实战要点: 缺页异常(Page Fault)是内存管理中最频繁的事件之一。当PTE的Present位为0时,MMU触发缺页异常,内核根据异常类型(有效/无效/保护错误)执行不同的处理流程,如分配物理页、从swap分区换入、写时复制(COW)等。

1.5 本章小结

本章建立了Linux内存管理子系统的全景视图,明确了三个核心概念:

  • 虚拟内存 为进程提供独立、连续的地址空间抽象,通过页表映射到物理内存。
  • 物理内存 是硬件RAM,由内核统一管理,通过伙伴系统和SLUB分配器分配。
  • MMU与页表 是地址转换的硬件基础和软件数据结构,多级页表结构在灵活性和性能之间取得平衡。