参考:分配策略、碎片与伙伴/slab 速查
基于通用操作系统概念 · 核于 2026-08
速查
- 逻辑地址 vs 物理地址:CPU/程序产生的是逻辑地址(相对程序起点,每进程独立);内存芯片上的真实地址是物理地址;MMU 翻译。
- 地址绑定三时机:编译时(绝对代码,不可重定位)< 加载时(加载改绝对,后不动)< 执行时(MMU 动态翻译,可搬移换页,现代 OS)。
- 连续分配三方案:单一连续分区(单道)< 固定分区(内碎片)< 动态分区(外碎片)。
- 内部碎片 vs 外部碎片:内=块内浪费(固定分区/伙伴取整,锁死不可用);外=块间散碎(动态分区,总够但拼不起)。
- 放置策略:首次适应(最快最常用)、最佳适应(产生极小碎片)、最坏适应(大块迅速耗尽)。
- 紧凑 compaction:搬移合并,需执行时绑定,停机开销大。
- 伙伴系统:2 的幂次分配/合并,O(log n),内碎片最坏 50%,是 Linux 物理页分配器核心。
- slab:内核同类型小对象池化复用,O(1),省构造开销;slub/slob 是变体。
- Linux 分层:伙伴系统(页)→ kmalloc(通用小块 slab)→ 专用 slab 缓存(对象)。
一、连续分配方案对比
| 方案 | 内存怎么分 | 碎片 | 多道 | 复杂度 | 代表 |
|---|---|---|---|---|---|
| 单一连续分区 | OS 区 + 一个用户区 | 无(单道) | 否 | 最简 | 早期单道批处理 |
| 固定分区 | 预切固定大小分区 | 内部碎片 | 是 | O(1) | IBM OS/360 MFT |
| 动态分区 | 按需恰好分配 | 外部碎片 | 是 | O(n) 扫链表 | 早期 Unix |
二、地址绑定三时机
| 时机 | 地址何时定 | 可重定位 | 搬移/换页 | 代表 |
|---|---|---|---|---|
| 编译时 | 编译生成绝对地址 | 否 | 不行 | 早期批处理绝对代码 |
| 加载时 | 加载时改成绝对 | 加载前可 | 加载后不行 | 可重定位目标码 |
| 执行时 | 运行期 MMU 动态翻译 | 随时 | 可以(紧凑/换页) | 现代 OS(虚拟内存) |
三、三种放置策略对比
| 策略 | 选哪个块 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| 首次适应 | 第一个够大 | 快,最常用 | 低地址碎片集中 | 通用默认 |
| 最佳适应 | 最小的够大 | 省大块 | 极小碎片多,外碎片最重 | 大块稀缺时慎用 |
| 最坏适应 | 最大的块 | 减少小碎片 | 大块迅速耗尽 | 极少用 |
四、碎片类型
| 内部碎片 | 外部碎片 | |
|---|---|---|
| 位置 | 分配块内部 | 空闲块之间 |
| 谁产生 | 固定分区、伙伴取整 | 动态分区 |
| 能否用 | 不能(锁死块内) | 理论能(不连续) |
| 解法 | slab/可变块 | 紧凑 / 分页 |
五、伙伴系统 vs slab
| 维度 | 伙伴系统 | slab |
|---|---|---|
| 管什么 | 物理页框(4KB 起) | 页内小对象(几十 B 起) |
| 块大小 | 2 的幂次(页的倍数) | 定长对象槽 |
| 复杂度 | O(log n) | O(1) |
| 内碎片 | 有(取整,最坏 50%) | 几乎无(按对象大小) |
| 用途 | Linux alloc_pages | Linux kmalloc/专用缓存 |
| 复用 | 块级合并 | 对象池化(省构造开销) |
六、易错点清单
- "逻辑地址就是物理地址":错。逻辑地址是 CPU/程序产生的,物理地址是内存芯片上的,由 MMU 翻译。没有 MMU 的早期裸机才相等。
- "地址绑定都是执行时":错。有三种时机——编译时(绝对代码)、加载时(加载改绝对)、执行时(动态翻译)。现代 OS 才用执行时。
- "内碎片和外碎片是一回事":错。内=块内浪费(固定分区),外=块间散碎(动态分区)。位置不同。
- "紧凑(compaction)随时能做":错。紧凑要求执行时绑定(地址可重定位),且是停机操作开销大。编译时/加载时绑定的进程搬了就地址全错。
- "最佳适应碎片最少":错。最佳适应(选最小够大块)恰恰外碎片最严重——每次剩极小一点点不可用。综合最佳是首次适应。
- "最坏适应浪费最大":错(针对内碎片而言不适用)。最坏适应的问题是大块迅速耗尽,不是浪费大——它每次切最大块,剩的反而能用。
- "伙伴系统没有内碎片":错。伙伴系统向上取整到 2 的幂(要 17KB 给 32KB),内碎片最坏近 50%。
- "slab 取代了伙伴系统":错。两者分层协同——slab 向伙伴系统要页建池,管页内小对象;伙伴系统管物理页框。
kmalloc大块仍走伙伴。 - "伙伴系统分配是 O(1)":错。分配/合并都是 O(log n)(最多分裂/合并 log n 档)。O(1) 的是 slab。
- "slab 的小对象每次都重新构造":错。slab 池化复用——预构造一批对象,分配时取已构造好的,释放时不真析构,省构造开销。
- "固定分区产生外部碎片":错。固定分区产生内部碎片(块内浪费);外部碎片是动态分区的产物。
- "动态分区没有碎片":错。动态分区无内碎片但有外碎片(块间散碎凑不成大块)。
七、进阶方向(链接其他叶)
- 操作系统概述 —— 内存管理在 OS 四大功能中的位置
- 分页、分段与虚拟内存 —— 非连续分配、页表、TLB、缺页中断、页面置换
- 进程与线程基础 —— 进程地址空间隔离