内存分配与碎片
medium操作系统内存分配碎片伙伴系统slab
内存碎片
外部碎片
空闲内存分散分布,总量足够但没有足够大的连续空闲块来满足请求。常见于分段管理。
内部碎片
分配给进程的内存块比实际需要的大,多余部分浪费。常见于分页管理(页大小4KB,请求4.1KB需分配2页=8KB)。
连续分配策略
| 策略 | 方法 | 特点 |
|---|---|---|
| 首次适应 | 从头找第一个够大的空闲块 | 速度快,低地址碎片多 |
| 最佳适应 | 找最小的满足要求的空闲块 | 碎片最小,搜索慢 |
| 最差适应 | 找最大的空闲块 | 剩余块仍可用,大块耗尽快 |
伙伴系统(Buddy System)
Linux 内核用伙伴系统管理物理页帧。核心思想:按 2 的幂次大小分块,分配时拆分,回收时合并伙伴块。
请求 21KB → 向上取整到 32KB:
256KB
├── 128KB
│ ├── 64KB
│ │ ├── 32KB ← 分配(内部碎片 11KB)
│ │ └── 32KB (空闲伙伴)
│ └── 64KB (空闲)
└── 128KB (空闲)
释放: 32KB → 与伙伴合并为 64KB → 合并为 128KB → ...
优点:O(log n) 分配/回收,有效减少外部碎片。缺点:内部碎片。
Slab 分配器
伙伴系统最小单位是页(4KB),但内核有大量小对象。Slab 为每种对象维护专用缓存池:
Slab(伙伴系统分配的页)
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
│obj │ │obj │ │free│ │obj │ │free│
│已用│ │已用│ │空闲│ │已用│ │空闲│
└────┘ └────┘ └────┘ └────┘ └────┘
每个对象大小相同(如 task_struct)
优势:零内部碎片、对象复用避免反复初始化、分配极快。
Linux 内存分配全景
- 用户态
malloc():小块用brk()扩展堆,大块(>128KB)用mmap()映射匿名页 - 内核态:伙伴系统管理物理页,Slab 管理小对象
生产高频题
内部碎片和外部碎片的区别?
内部碎片:分配的内存大于实际需要(分页多余部分)。外部碎片:空闲内存总量够但不连续(分段中常见)。
Linux 如何管理物理内存?
伙伴系统管理物理页帧(按2的幂次分配),Slab 分配器管理内核小对象(在伙伴系统之上)。