跳到主要内容

内存管理

内存管理的目标是在多个进程间高效、安全地分配物理内存,并提供地址隔离与保护。从早期的连续分配,到现代以分页为主的方案,核心都是解决"如何把虚拟地址映射到物理地址"以及"如何减少碎片"。

连续分配

最简单的方案把进程整个装入一块连续物理区。常见三种放置策略:

  • 首次适配(First-Fit):从低地址开始找第一个足够大的空闲块,速度较快。
  • 最佳适配(Best-Fit):找最小但足够的空闲块,减少大块浪费,但会产生大量小碎片。
  • 最坏适配(Worst-Fit):找最大空闲块切,试图保留较多大块,实际效果常最差。

连续分配实现简单,只用一个基址寄存器即可重定位,缺点是会产生外部碎片,需要通过compaction(内存紧缩)定期整理。

分页与页表

分页把虚拟地址空间和物理内存都切成等长页面(典型 4KB),通过页表把虚拟页映射到物理页帧(称为page frame)。优点是消除了外部碎片,任意物理页帧都可使用;代价是引入了内部碎片(页内未用部分)与页表本身的开销。

地址转换硬件(MMU)过程:

虚拟地址 = [ 页号 VPN | 页内偏移 offset ]
物理地址 = [ 页帧号 PFN | 页内偏移 offset ]
PFN = 页表[VPN]

多级页表

单级页表的大小与虚拟地址空间成正比,64 位系统无法承受。多级页表按页号分层,只为实际使用的页区间建立子表,显著节省内存。x86-64 使用四级页表(PML4 → PDPT → PD → PT),ARM64 类似。

分段

分段以"逻辑段"为单位(代码段、数据段、栈段),每段长度可变,提供开发者视角的地址空间。段号+段内偏移构成虚拟地址。段的最大问题是外部碎片与段长不固定带来的管理复杂。

段页式

实际系统往往结合两者:先按段划分逻辑空间,再在段内分页。程序员与编译器看到段,MMU 看到页。这样既保留逻辑清晰,又得到分页的物理优势,Intel x86 架构就提供这种机制。

碎片小结

类型出现在解决方案
内部碎片固定大小分配单元内未用部分分页(无法完全消除,只能减小页大小)
外部碎片空闲块零散、不连续紧缩(连续分配)或非连续分配(分页)

现代通用 OS 几乎都以分页为底层机制,再叠加换出与共享映射等高级特性。