分段(Segmentation)

按逻辑划分内存,每个段对应程序的一个逻辑单元(代码段、数据段、栈段等)。

  • 地址 = 段号 + 段内偏移
  • 段长度可变,符合程序逻辑结构
  • 优点:便于共享和保护(比如代码段只读)
  • 缺点:外部碎片——段大小不一,内存里会出现零散的空洞,难以利用

分页(Paging)

把物理内存和虚拟地址空间都切成固定大小的块(页框/页,通常 4KB)。

  • 地址 = 页号 + 页内偏移
  • 通过页表把虚拟页号映射到物理页框号
  • 优点:无外部碎片,内存利用率高
  • 缺点:内部碎片(最后一页可能没用满);页表本身占内存,多级页表解决大地址空间问题

TLB(快表):页表查询要访问内存,太慢。TLB 是硬件缓存,缓存最近用过的页表项,命中率通常 >99%,大幅加速地址转换。

段页式

结合两者:先分段,每段再分页。兼顾逻辑清晰和物理高效,现代 x86 基本就是这个模型(但 Linux 把段都设成 0 基址,实际上退化成纯分页)。

虚拟内存

核心思想:程序不需要全部装入内存才能运行,只把当前用到的页加载进来,其余放在磁盘(swap)。

  • 每个进程有独立的虚拟地址空间,互相隔离
  • 访问不在内存的页 → 缺页中断(Page Fault) → OS 从磁盘调入该页
  • 如果内存满了,需要先置换一个旧页出去

好处:

  • 程序可以比物理内存大
  • 进程隔离,安全
  • 多进程共享物理内存(写时复制 COW)

页面置换算法

内存满了,选哪个页换出去?

算法 思路 特点
OPT(最优) 换出未来最长时间不用的页 理论最优,实际不可实现(无法预知未来),用于评估基准
FIFO 换出最早进入内存的页 实现简单,但可能换出常用页;有 Belady 异常(增加页框反而缺页率上升)
LRU(最近最少使用) 换出最久没被访问的页 性能接近 OPT,工程常用;精确实现需要时间戳或链表,开销较大
Clock(时钟/二次机会) 给每页一个访问位,循环扫描,访问位为 1 则清零跳过,为 0 则换出 LRU 的近似实现,开销小,Linux 实际使用的是改进版
LFU(最不常用) 换出访问次数最少的页 对突发访问不友好,历史计数可能失真

工程实际:Linux 用的是改进版 Clock(active/inactive 两个链表),近似 LRU,兼顾性能和开销。

总结

分段解决逻辑组织,分页解决物理碎片,虚拟内存让程序突破物理内存限制,页面置换算法决定内存满时踢谁出去——LRU 最常用,Clock 是工程近似。