1. 内存管理概述
内存管理是 Linux 内核最核心的子系统之一,它直接决定了系统的并发能力、响应速度和资源利用率。本章从宏观架构出发,建立对 MMU(内存管理单元)、虚拟内存 和 内核内存布局 的清晰认知,为后续深入伙伴系统和虚拟内存优化打下坚实基础。
学习目标:理解虚拟内存如何解决物理内存不足与进程隔离问题;掌握 MMU 的分页转换机制;熟悉 Linux 内核在 x86-64 架构下的地址空间划分。
1.1 虚拟内存的核心思想
虚拟内存为每个进程提供独立的、连续的、大小为 264 字节(x86-64)的地址空间。进程无需关心物理内存的实际分布,也无需担心其他进程的干扰。
| 特性 | 物理内存直接管理 | 虚拟内存管理 |
|---|---|---|
| 地址空间 | 所有进程共享同一物理地址空间 | 每个进程拥有独立的虚拟地址空间 |
| 隔离性 | 进程间可互相读写内存,无保护 | 进程间完全隔离,内核控制映射 |
| 内存大小 | 受限于物理 RAM 容量 | 可超过物理 RAM(通过交换/分页) |
| 碎片问题 | 易产生外部碎片 | 通过页表映射消除外部碎片 |
| 编程复杂度 | 程序员需手动管理内存布局 | 程序员使用连续虚拟地址,简单安全 |
关键指标:虚拟内存的引入使得“按需分页”(Demand Paging)成为可能——只有真正访问到的页面才会被加载到物理内存,大幅提高了内存利用率。
1.2 MMU 与地址转换机制
MMU(Memory Management Unit)是 CPU 内部负责将虚拟地址转换为物理地址的硬件模块。Linux 内核通过配置页表来告诉 MMU 如何完成这一映射。
以 x86-64 架构的 4 级页表为例,转换过程如下:
- 虚拟地址分解: 64 位虚拟地址被拆分为 5 个部分(4 级页表 + 偏移)。
- 页全局目录(PGD): 由 CR3 寄存器指向,索引第 1 级。
- 页上级目录(PUD): 索引第 2 级。
- 页中间目录(PMD): 索引第 3 级。
- 页表(PTE): 索引第 4 级,得到物理页帧号(PFN)。
- 页内偏移: 物理地址 = PFN × 页大小 + 偏移。
性能陷阱:每次地址转换都需要 4 次内存访问(4 级页表)。TLB(Translation Lookaside Buffer)作为页表项的硬件缓存,命中率通常超过 99%。当 TLB 未命中时,MMU 必须遍历页表,造成数十纳秒的延迟。大页面(Huge Pages)可以减少页表层级,是性能调优的重要手段。
1.3 Linux 内核地址空间布局
在 x86-64 架构下,Linux 将虚拟地址空间划分为用户空间和内核空间。内核空间位于高地址区域,用户空间位于低地址区域,两者通过页表权限位隔离。
| 区域 | 地址范围 | 用途 |
|---|---|---|
| 用户空间 | 0x0000 0000 0000 0000 – 0x0000 7FFF FFFF FFFF | 进程代码、堆、栈、共享库、mmap 区域 |
| 内核空间 | 0xFFFF 8000 0000 0000 – 0xFFFF FFFF FFFF FFFF | 内核代码、模块、直接映射区、vmalloc、固定映射 |
| 直接映射区 | 0xFFFF 8880 0000 0000 – 0xFFFF C87F FFFF FFFF | 物理内存线性映射(减去一定偏移),用于 slab 分配器、伙伴系统 |
| vmalloc 区 | 0xFFFF C900 0000 0000 – 0xFFFF E8FF FFFF FFFF | 非连续内存分配,用于模块、大块内核缓冲区 |
| 固定映射区 | 0xFFFF FFFF 8000 0000 – 0xFFFF FFFF FFFF FFFF | 用于 ACPI、APIC 等硬件寄存器映射 |
1.4 内存管理子系统架构
Linux 内存管理子系统采用分层设计,从下到上依次为:
- 硬件层: MMU、TLB、物理 RAM、DMA 控制器。
- 页表管理层: 负责页表的创建、销毁、查找和权限控制。
- 物理内存分配器: 伙伴系统(Buddy System)负责连续物理页框的分配与回收。
- slab 分配器: 基于伙伴系统,提供小对象(如 task_struct、inode)的高速缓存。
- 虚拟内存管理层: 管理进程的 VMA(虚拟内存区域),处理缺页异常。
- 文件映射与交换层: 负责文件页缓存、匿名页、swap 换入换出。
调优切入点:伙伴系统负责大块连续物理内存的分配,是 slab 分配器和 vmalloc 的基础。伙伴系统的碎片化程度直接影响系统长时间运行的稳定性。后续章节将深入分析伙伴算法的实现、碎片预防机制以及如何通过调整
min_free_kbytes、watermark 等参数进行性能调优。
1.5 关键数据结构速览
在进入伙伴系统之前,需要熟悉几个核心数据结构:
| 数据结构 | 所在文件 | 作用 |
|---|---|---|
struct page |
include/linux/mm_types.h | 描述一个物理页框(4KB),包含 flags、引用计数、lru 链表等 |
struct zone |
include/linux/mmzone.h | 描述一个内存区域(DMA、DMA32、Normal、Movable),包含伙伴系统 free_area 数组 |
struct free_area |
include/linux/mmzone.h | 伙伴系统的核心,每个 order 对应一个链表,管理空闲页块 |
struct vm_area_struct |
include/linux/mm_types.h | 描述进程虚拟地址空间中的一个连续区域(VMA) |
struct mm_struct |
include/linux/mm_types.h | 描述进程的完整内存空间,包含页表基址、VMA 链表、brk 等 |
快速记忆:
struct page 是物理内存的最小管理单元;struct zone 是区域管理器;struct free_area 是伙伴系统的“货架”;struct vm_area_struct 是进程的“虚拟内存地图”。