把物理内存切成固定大小的块叫页框(Frame);把进程逻辑地址空间也切成同样大小的块叫页(Page)。
通过页表(Page Table)建立映射,CPU 访问时硬件自动查表完成地址转换。
页大小通常是 4KB(2 的 n 次方),页内偏移直接作为物理地址低位是硬件实现的关键。
32 位系统页大小 4KB → 偏移 12 位,剩余 20 位用于页号。
一级页表需 2²⁰ = 1M 个页表项,每个进程 4MB 页表!100 个进程 = 400MB,太浪费。
→ 引入多级页表:只给实际使用的二级页表分配内存,大幅节省空间。
每次内存访问都先查页表 → 两次内存访问,速度慢一倍。
→ 引入 TLB:CPU 内的专用高速缓存,存最近用过的页号→页框号映射。
TLB 命中 → 只需一次内存访问!命中率通常 > 99%。
分页是物理角度划分(固定大小,对程序员透明),分段是逻辑角度划分。
程序天然分为:代码段、数据段、堆、栈,每段有独立的段号 + 段内偏移。
通过段表记录每段的基址(Base)和界限(Limit),访问时先查段表,再做越界检查。
分段中,段大小不一,分配释放后会在内存中留下外部碎片(不连续的小空闲区)。
解决方法:内存紧缩(Compaction) — 把所有已分配段向一端移动,合并空闲区。代价是移动成本高。
分段和分页各有优劣 → 段页式 = 分段 + 分页,取两者之长!
思路:先按逻辑分段(方便共享和保护),每段内部再按固定大小分页(消除外部碎片)。
地址结构:段号 | 页号 | 页内偏移,每个段有一张页表,系统有一张段表。
| 对比维度 | 分页 | 分段 | 段页式 |
|---|---|---|---|
| 划分依据 | 物理角度,固定大小 | 逻辑角度,不定长 | 先逻辑分段,段内分页 |
| 块大小 | 固定(如 4KB) | 不固定 | 段不定长,页固定 |
| 碎片问题 | 内部碎片 | 外部碎片 | 无外部碎片,有少量内部碎片 |
| 共享与保护 | 困难 | 方便 | 方便 |
| 表结构 | 页表(可能多级) | 段表(基址+界限) | 段表 + 每段的页表 |
| 地址转换 | 页号→查页表→页框号+偏移 | 段号→查段表→基址+偏移(需越界检查) | 段号→段表→页表→页框+偏移 |
| 典型应用 | 大多数 OS(Linux、Windows) | 已基本被扁平模型取代 | Intel x86 底层 |
🔹 分页:内存切成等大"块",用页表映射,解决外部碎片,但有内部碎片。
🔹 分段:按程序逻辑分"段",每段大小不一,方便共享保护,但有外部碎片。
🔹 段页式:先分段再分页,集两家之长,但地址转换需两次查表,依赖 TLB 加速。