1. 内存管理概述
内存管理是Linux内核最核心的子系统之一,它负责在有限的物理内存与无限的虚拟地址空间之间建立高效、安全的映射桥梁。本章从宏观视角出发,首先厘清内存管理子系统的作用边界,然后深入剖析物理内存与虚拟内存的本质区别,最后介绍支撑这一切的硬件基础——MMU(内存管理单元)。
1.1 Linux内存管理子系统的作用
Linux内存管理子系统承担着以下关键职责:
- 地址空间隔离:为每个进程提供独立的虚拟地址空间,防止进程间相互干扰。
- 内存分配与回收:管理物理页面的分配、释放、回收和交换。
- 页表管理:维护虚拟地址到物理地址的映射关系,支持按需分页。
- 缓存与缓冲区管理:优化磁盘I/O和文件系统访问性能。
- 内存映射:支持文件映射、共享内存、设备I/O映射等高级功能。
- SLAB/SLUB分配器:为内核对象提供高效、低碎片的小内存分配机制。
核心指标:在x86-64架构上,Linux支持48位虚拟地址空间(256TB用户空间 + 256TB内核空间),物理地址最大支持4PB(52位)。页表层级为4级(PGD→P4D→PUD→PMD→PTE),在启用5级页表时扩展为5级。
1.2 物理内存与虚拟内存的概念
物理内存是硬件实际提供的RAM芯片,而虚拟内存是操作系统为每个进程抽象出的连续、独立的地址空间。两者通过页表建立动态映射。
| 对比维度 | 物理内存 | 虚拟内存 |
|---|---|---|
| 本质 | 硬件DRAM芯片,容量有限 | 操作系统抽象,每个进程独享 |
| 地址空间 | 从0到物理内存上限(如4GB/16GB) | 从0到虚拟地址上限(如256TB) |
| 连续性 | 物理地址可能不连续(NUMA节点) | 对进程呈现连续线性空间 |
| 安全性 | 无保护,任何物理地址都可访问 | 页表权限控制,用户态无法访问内核空间 |
| 共享性 | 所有进程共享同一物理内存 | 每个进程独立,通过mmap实现共享 |
| 交换能力 | 物理内存不足时需换出 | 虚拟内存可以大于物理内存(借助交换分区) |
关键理解:虚拟内存的核心价值在于“隔离”和“抽象”。隔离让进程A的崩溃不会影响进程B;抽象让程序员无需关心物理内存的碎片化、NUMA拓扑等硬件细节,只需面对一个连续的、大小几乎无限的地址空间。
1.3 MMU硬件基础
MMU(Memory Management Unit)是CPU内部负责地址转换的硬件模块。它接收CPU发出的虚拟地址,通过查询页表(TLB加速)将其转换为物理地址,同时检查访问权限。
MMU的核心工作流程如下:
- CPU发出虚拟地址:指令或数据访问产生一个48位(x86-64)虚拟地址。
- TLB查找:MMU首先在TLB(Translation Lookaside Buffer,快表)中查找虚拟地址对应的物理地址。如果命中,直接返回。
- 页表遍历:如果TLB未命中,MMU硬件自动遍历页表(多级页表结构),逐级查找页表项。
- 权限检查:检查页表项中的权限位(读/写/执行、用户/内核、存在位等)。
- 地址转换:将虚拟页号转换为物理页帧号,加上页内偏移得到最终物理地址。
- TLB缓存:将新转换结果写入TLB,加速后续访问。
性能陷阱:TLB未命中会导致MMU硬件遍历多级页表,每次遍历都需要访问内存(可能触发多级cache miss),开销极大。Linux内核通过大页(HugeTLB、透明大页)减少页表层级和TLB压力,是性能优化的关键手段。
1.4 虚拟地址到物理地址的转换流程(SVG架构图)
下图展示了x86-64架构下,MMU将虚拟地址转换为物理地址的完整流程,包含4级页表遍历和TLB加速路径:
1.5 页表项结构(PTE)关键字段
页表项(Page Table Entry)是页表的基本单元,每个PTE对应一个4KB物理页帧(或大页)。x86-64架构的PTE为64位,关键字段如下:
| 位域 | 名称 | 说明 |
|---|---|---|
| Bit 0 | Present (P) | 页面是否在物理内存中。为0时访问触发缺页异常 |
| Bit 1 | Read/Write (R/W) | 0=只读,1=可读写 |
| Bit 2 | User/Supervisor (U/S) | 0=仅内核可访问,1=用户态也可访问 |
| Bit 3 | Page-Level Write-Through (PWT) | 控制cache写策略:0=写回,1=写透 |
| Bit 4 | Page-Level Cache Disable (PCD) | 1=禁止该页的cache缓存 |
| Bit 5 | Accessed (A) | 硬件自动置1,表示页面被访问过(用于页面回收算法) |
| Bit 6 | Dirty (D) | 硬件自动置1,表示页面被写入过(用于回写交换) |
| Bit 7 | Page Attribute Table (PAT) | 配合PAT寄存器控制内存类型(UC/WC/WT/WB等) |
| Bit 8 | Global (G) | 1=全局页,TLB刷新生效时保留(常用于内核空间) |
| Bits 9-11 | Ignored/Software Available | 供操作系统自由使用(Linux用于存储页状态标志) |
| Bits 12-51 | Physical Address (PFN) | 物理页帧号(Page Frame Number),共40位,支持最大1TB物理内存(4KB页) |
| Bits 52-62 | Reserved/MBZ | 保留位,必须为0 |
| Bit 63 | No Execute (NX) | 1=禁止执行该页代码(硬件DEP保护) |
Linux内核利用:Linux在PTE的软件可用位(Bits 9-11)中存储了
_PAGE_SOFT_DIRTY、_PAGE_SPECIAL等标志,用于实现内存脏页跟踪、设备映射等高级功能。NX位(Bit 63)是x86-64新增的硬件安全特性,Linux内核从2.6.8开始支持,用于阻止栈溢出攻击。
1.6 内存管理子系统整体架构(SVG软件架构图)
下图展示了Linux内存管理子系统的分层架构,从硬件MMU到上层系统调用接口:
1.7 本章小结
本章建立了内存管理的宏观认知框架:
- 内存管理子系统是Linux内核最复杂的子系统之一,涵盖地址空间隔离、分配回收、页表管理、缓存映射等核心功能。
- 物理内存 vs 虚拟内存:物理内存是硬件资源,虚拟内存是OS抽象,两者通过页表动态映射,实现隔离、共享和超量使用。
- MMU硬件是地址转换的物理执行者,TLB加速是其性能关键,页表项中的权限位和状态位为内核提供了丰富的控制能力。
- 分层架构从系统调用接口到底层硬件抽象,每一层都有明确的职责边界,后续章节将逐层深入。