🧠 操作系统内存管理

分页 · 分段 · 段页式 — 交互式动态图解
📄 什么是分页(Paging)?

物理内存切成固定大小的块叫页框(Frame);把进程逻辑地址空间也切成同样大小的块叫页(Page)

通过页表(Page Table)建立映射,CPU 访问时硬件自动查表完成地址转换。

页大小通常是 4KB(2 的 n 次方),页内偏移直接作为物理地址低位是硬件实现的关键。

💡 核心思想:物理内存和进程地址空间都划分为固定大小的单元,通过页表建立映射。
优点:无外部碎片,分配简单。
缺点:有内部碎片(页内用不满),大地址空间页表本身很大。
动画1:逻辑地址 → 物理地址转换
🗂️ 动画2:多级页表(32位系统)

32 位系统页大小 4KB → 偏移 12 位,剩余 20 位用于页号。

一级页表需 2²⁰ = 1M 个页表项,每个进程 4MB 页表!100 个进程 = 400MB,太浪费。

→ 引入多级页表:只给实际使用的二级页表分配内存,大幅节省空间。

🚀 动画3:TLB 快表加速

每次内存访问都先查页表 → 两次内存访问,速度慢一倍。

→ 引入 TLB:CPU 内的专用高速缓存,存最近用过的页号→页框号映射。

TLB 命中 → 只需一次内存访问!命中率通常 > 99%。

📐 什么是分段(Segmentation)?

分页是物理角度划分(固定大小,对程序员透明),分段是逻辑角度划分。

程序天然分为:代码段数据段,每段有独立的段号 + 段内偏移

通过段表记录每段的基址(Base)界限(Limit),访问时先查段表,再做越界检查

💡 核心思想:按程序逻辑结构划分内存,每段大小不固定。
优点:无内部碎片,支持共享和保护。
缺点:有外部碎片,需要内存紧缩(Compaction)。
动画1:段表地址转换过程
🧩 动画2:外部碎片 & 内存紧缩

分段中,段大小不一,分配释放后会在内存中留下外部碎片(不连续的小空闲区)。

解决方法:内存紧缩(Compaction) — 把所有已分配段向一端移动,合并空闲区。代价是移动成本高

🔗 什么是段页式?

分段和分页各有优劣 → 段页式 = 分段 + 分页,取两者之长!

思路:先按逻辑分段(方便共享和保护),每段内部再按固定大小分页(消除外部碎片)。

地址结构段号 | 页号 | 页内偏移,每个段有一张页表,系统有一张段表。

兼具两者优点:分段的逻辑独立性、共享保护 + 分页的无外部碎片。
🏗️ 实际应用:Intel x86 处理器的内存管理采用段页式。
🔄 动画1:段页式地址转换全流程
📊 动画2:三种方式内存布局对比
📊 分页 vs 分段 vs 段页式 全面对比
对比维度分页分段段页式
划分依据物理角度,固定大小逻辑角度,不定长先逻辑分段,段内分页
块大小固定(如 4KB)不固定段不定长,页固定
碎片问题内部碎片外部碎片无外部碎片,有少量内部碎片
共享与保护困难方便方便
表结构页表(可能多级)段表(基址+界限)段表 + 每段的页表
地址转换页号→查页表→页框号+偏移段号→查段表→基址+偏移(需越界检查)段号→段表→页表→页框+偏移
典型应用大多数 OS(Linux、Windows)已基本被扁平模型取代Intel x86 底层
💡 一句话总结

🔹 分页:内存切成等大"块",用页表映射,解决外部碎片,但有内部碎片。

🔹 分段:按程序逻辑分"段",每段大小不一,方便共享保护,但有外部碎片。

🔹 段页式:先分段再分页,集两家之长,但地址转换需两次查表,依赖 TLB 加速。

🧭 学习路径:先搞懂分页地址转换 → 理解多级页表和 TLB → 再学分段逻辑划分 → 最后理解段页式融合两者。