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 级页表为例,转换过程如下:

  1. 虚拟地址分解: 64 位虚拟地址被拆分为 5 个部分(4 级页表 + 偏移)。
  2. 页全局目录(PGD): 由 CR3 寄存器指向,索引第 1 级。
  3. 页上级目录(PUD): 索引第 2 级。
  4. 页中间目录(PMD): 索引第 3 级。
  5. 页表(PTE): 索引第 4 级,得到物理页帧号(PFN)。
  6. 页内偏移: 物理地址 = PFN × 页大小 + 偏移。
MMU 地址转换流程(x86-64 4 级页表) 虚拟地址 (48 位有效) PGD 索引 (9 bit) PUD 索引 (9 bit) PMD 索引 (9 bit) PTE 索引 (9 bit) 页内偏移 (12 bit) PGD (CR3 指向) PUD PMD PTE (页表) 物理页帧 (PFN) 物理地址 = PFN × 4K + 偏移 TLB 缓存最近使用的 PTE
性能陷阱:每次地址转换都需要 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 等硬件寄存器映射
Linux x86-64 虚拟地址空间布局 用户空间 (User Space) 0x0000 0000 0000 0000 – 0x0000 7FFF FFFF FFFF 代码段 | 数据段 | 堆 | 栈 | 共享库 | mmap 每个进程独立,页表权限位限制内核访问 边界 内核空间 (Kernel Space) 0xFFFF 8000 0000 0000 – 0xFFFF FFFF FFFF FFFF 直接映射区 (Direct Mapping) — 伙伴系统 / slab vmalloc 区 — 非连续内存分配 固定映射区 (Fixed Mapping) — 硬件寄存器 内核代码 / 模块 / 栈 用户态通过系统调用陷入内核,CPU 切换页表权限位

1.4 内存管理子系统架构

Linux 内存管理子系统采用分层设计,从下到上依次为:

  • 硬件层: MMU、TLB、物理 RAM、DMA 控制器。
  • 页表管理层: 负责页表的创建、销毁、查找和权限控制。
  • 物理内存分配器: 伙伴系统(Buddy System)负责连续物理页框的分配与回收。
  • slab 分配器: 基于伙伴系统,提供小对象(如 task_struct、inode)的高速缓存。
  • 虚拟内存管理层: 管理进程的 VMA(虚拟内存区域),处理缺页异常。
  • 文件映射与交换层: 负责文件页缓存、匿名页、swap 换入换出。
Linux 内存管理子系统分层架构 用户进程 (User Process) 系统调用 (sys_mmap / sys_brk) 虚拟内存管理 (VMA / 缺页异常) 文件映射 / 交换层 (Page Cache / Swap) 伙伴系统 + slab 分配器 MMU / TLB / 物理 RAM
调优切入点:伙伴系统负责大块连续物理内存的分配,是 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 是进程的“虚拟内存地图”。