1. 内存管理概述:Linux内存管理架构、虚拟内存与物理内存、内存分配器的作用
1.1 Linux 内存管理架构全景
Linux 内核的内存管理子系统是操作系统最核心、最复杂的模块之一。它负责在有限的物理内存资源下,为进程、内核、缓存、设备等所有系统组件提供高效、安全、公平的内存分配与回收服务。理解其分层架构是掌握 Slab 分配器与内存碎片调优的前提。
下图展示了 Linux 内存管理的核心分层架构,从硬件到用户空间,每一层都承担着特定的抽象与职责:
架构要点: 用户态通过系统调用陷入内核;VMA 层管理虚拟地址空间;伙伴系统管理物理页框;Slab 分配器在伙伴系统之上提供小对象缓存;页缓存层处理文件与匿名页的 I/O 优化。每一层都直接影响内存碎片与分配效率。
1.2 虚拟内存与物理内存
虚拟内存是现代操作系统内存管理的基石。每个进程拥有独立的 4GB(32位)或 128TB(64位)虚拟地址空间,通过 MMU 和页表映射到物理内存。这种抽象带来了隔离、安全、以及“大于物理内存”的错觉。
| 特性 | 虚拟内存 | 物理内存 |
|---|---|---|
| 地址空间 | 每个进程独立,连续线性 | 全局共享,可能不连续 |
| 大小 | 受 CPU 位宽限制(如 48位 = 256TB) | 受硬件容量限制(如 64GB) |
| 分配粒度 | 页(4KB / 2MB / 1GB) | 页框(4KB 或大页) |
| 碎片来源 | VMA 碎片(地址空间空洞) | 外部碎片(伙伴系统无法合并) |
| 与 Slab 的关系 | Slab 分配器不直接管理虚拟地址 | Slab 从伙伴系统获取物理页,再切分为小对象 |
下图展示了虚拟地址到物理地址的映射过程,以及 Slab 分配器在其中扮演的角色:
关键理解: Slab 分配器并不直接操作虚拟地址或页表。它从伙伴系统获取连续的物理页框(通常为 2^order 个页),然后在页框内部进行细粒度划分,为内核对象(如 inode、task_struct、dentry)提供高速缓存。这种“先大块、再细分”的模式是控制内部碎片的关键。
1.3 内存分配器的作用
内存分配器是内核内存管理的“最后一公里”执行者。不同的分配器服务于不同的场景和粒度需求。下表对比了 Linux 内核中主要的内存分配器及其职责:
| 分配器 | 管理粒度 | 主要用途 | 碎片类型 |
|---|---|---|---|
| 伙伴系统 (Buddy) | 物理页框 (4KB ~ 4MB) | 物理页框分配与回收;大块连续内存 | 外部碎片(页框无法合并) |
| Slab 分配器 | 小对象 (32B ~ 8KB) | 内核对象缓存(inode、dentry、task_struct) | 内部碎片(对象大小与 slab 不匹配) |
| 页缓存 (Page Cache) | 页 (4KB) | 文件页与匿名页缓存;I/O 加速 | 页缓存碎片(回收延迟) |
| vmalloc | 页 (4KB) 非连续 | 需要大块虚拟连续但物理不连续的内存 | 虚拟地址碎片 |
| percpu 分配器 | 小对象 / 页 | 每 CPU 变量,避免锁竞争 | 每 CPU 碎片 |
下图展示了从伙伴系统到 Slab 分配器的完整分配链路,以及碎片产生的关键节点:
碎片调优的核心矛盾: 伙伴系统追求大块连续物理内存,但频繁分配释放会导致外部碎片;Slab 分配器追求小对象快速复用,但对象大小与 slab 对齐不当会产生内部碎片。本课程后续章节将深入分析这两种碎片的成因、检测方法以及调优策略。
1.4 为什么 Slab 分配器是调优焦点
在 Linux 内核中,Slab 分配器承担着最频繁、最细粒度的内存分配任务。几乎所有内核数据结构的创建与销毁都经过 Slab 分配器。其性能与碎片状况直接影响系统整体吞吐量、响应延迟以及内存利用率。
- 高频调用: 每次打开文件、创建进程、网络收发都会触发 Slab 分配。
- 碎片敏感: 内部碎片虽然单次浪费小,但累积后可能达到数百 MB。
- 调优可见: 通过
/proc/slabinfo和slabtop可直接观察每个缓存的分配情况。 - 与伙伴系统联动: Slab 回收页框时,若伙伴系统无法合并,则碎片问题向上传递。