内存管理
核心问题只有一个:如何在有限、异构、昂贵的物理存储资源之上,构造一个安全、可扩展、对程序友好的逻辑地址世界。
一、问题起点:物理内存的客观约束
1.1 分层存储器体系(Memory Hierarchy)
物理现实:
- 存储介质在**容量、速度、成本**上不可兼得
- 由此形成层级结构:寄存器 → Cache → 主存 → 外存
结论:
内存管理的本质,是在分层存储器体系之上进行数据放置与迁移决策。
1.2 存储管理器的职责
操作系统中负责内存的核心子系统,其职责不是“分配内存”,而是:
- 记录资源状态(使用 / 空闲)
- 进行空间隔离(Protection)
- 执行地址映射(Translation)
- 决定数据驻留位置(Placement & Replacement)
二、第一阶段:无存储器抽象(Bare Machine Model)
2.1 直接暴露物理地址的问题
在无抽象模型下:
- 程序直接使用物理地址
- 任意进程可读写全部内存
导致两个根本性缺陷:
- **无法隔离**:安全性不可控
- **无法并发**:多道程序设计几乎不可实现
2.2 静态重定位的历史方案
如 IBM 360:
- 通过编译期或加载期地址映射
- 逻辑地址 ≈ 偏移后的物理地址
关键认知:
这不是“抽象”,只是一次性地址修正。
三、核心抽象的诞生:地址空间(Address Space)
3.1 地址空间的本质定义
地址空间 = 一组逻辑地址的有序集合
关键不是“地址”,而是:
- 每个进程拥有**独立命名空间**
- 相同地址值 ≠ 相同物理位置
这与编程语言中的作用域 / 命名空间是同一类抽象。
3.2 抽象带来的两个核心能力
运行多个程序而互不干扰,必须解决:
- **保护(Protection)**:禁止非法访问
- **重定位(Relocation)**:地址可移动
3.3 基址 / 界限寄存器模型
- 基址寄存器:映射起点
- 界限寄存器:合法范围
认知层结论:
这是最小可用的地址空间实现,但扩展性极差。
四、资源压力的应对:交换与连续内存管理
4.1 局部性原理(Locality)
程序行为呈现:
- 时间局部性
- 空间局部性
这是虚拟内存一切机制的理论基础。
4.2 交换(Swapping)的思想
- 整个进程作为单位换入 / 换出
- 用磁盘换取并发度
问题:
- 粗粒度
- 高开销
- 容易产生碎片
4.3 连续内存的空闲管理
两类本质模型:
- 位图(Bitmap):空间换时间
- 链表(Free List):时间换空间
所有“首次 / 最佳 / 最差 / 快速适配”算法,本质上都是:
在碎片率与搜索成本之间取舍
五、质变点:虚拟内存(Virtual Memory)
5.1 抽象升级
地址空间 ≠ 物理内存大小
虚拟内存将地址空间切分为页(Page):
- 逻辑上连续
- 物理上离散
5.2 页、页框与映射
- 虚拟页(VP)
- 物理页框(PP)
- 页表(Page Table)描述映射关系
访问不存在映射的页 → 缺页中断
六、地址转换体系:MMU + 页表 + TLB
6.1 MMU 的角色定位
MMU 不是“操作系统组件”,而是:
硬件执行抽象的载体
职责:
- 虚拟地址 → 物理地址
- 权限校验
6.2 页表的逻辑模型
每个页表项(PTE)至少包含:
- 有效位
- 物理页号 / 磁盘地址
- 权限位(R/W/X)
- 状态位(访问 / 修改)
6.3 TLB:缓存加速抽象
TLB 的本质:
地址转换结果的高速缓存
它将一次可能需要多次内存访问的操作,压缩为一次硬件并行匹配。
七、规模问题:大地址空间的页表设计
7.1 多级页表
- 按需创建
- 空间换时间
7.2 倒排页表
- 以物理页为中心
- 必须依赖 TLB
统一认知:
页表设计的本质是:稀疏映射的压缩表达。
八、多进程语义:共享、隔离与保护
8.1 虚拟内存的进程视角
- 地址相同 ≠ 数据相同
- 物理页可被多个地址空间映射
8.2 共享的工程价值
- 共享库
- 只读代码
- 写时复制(Copy-on-Write)
8.3 内存保护模型
权限控制并不作用于“物理内存”,而是:
作用于地址空间到物理页的映射关系
九、缓存淘汰的统一模型:页面置换算法
9.1 统一抽象
页面置换 ≈ 缓存淘汰
9.2 算法谱系
- OPT:理论上界
- FIFO:时间近似
- LRU:访问历史近似
- Clock / Aging:工程折中
- Working Set:程序语义感知
核心权衡:
- 精确度
- 维护成本
- 硬件支持
十、系统稳定性问题:颠簸与负载控制
- 缺页率(PFF)
- 局部 / 全局分配
- 负载削减
目标只有一个:
防止系统进入自激振荡(Thrashing)
十一、分段、分页与历史融合
11.1 分段的动机
- 程序语义可见
- 天然支持共享与保护
11.2 分页的动机
- 支持虚拟内存
- 消除外部碎片
11.3 段页式模型
- MULTICS
- x86(GDT / LDT + Paging)
结论:
分段解决“语义”,分页解决“规模”。
十二、进程内存布局与系统调用接口
- Code / Data / BSS
- Heap(brk / sbrk / mmap)
- Stack
- Shared Library
- Memory-mapped Files
现代内存管理已高度依赖 mmap 作为统一抽象接口。
十三、用户态分配器:再一次抽象
13.1 malloc 的真实职责
malloc 并不管理“内存”,而是:
管理一段虚拟地址区间的子分配
13.2 分配器的核心设计问题
- 空闲块组织
- 放置策略
- 分割与合并
- 并发优化(Thread Cache)
所有实现(ptmalloc / jemalloc / tcmalloc)都是在这组问题上的不同取舍。
十四、异常与中断:抽象失效的处理路径
14.1 页异常类型
- 未映射
- 不在内存
- 写保护
- 权限违规
14.2 缺页中断处理流程
- 保存现场
- 判定合法性
- 选择牺牲页
- IO 交换
- 更新映射
- 恢复执行
十五、虚拟化场景下的内存管理
- GVA → GPA → HPA
- Shadow Page Table
- EPT / NPT
结论:
虚拟化并没有引入新问题,只是把“地址转换”堆叠了一层。
十六、常见内存错误的抽象视角
所有内存错误,本质都源于:
程序假设的地址语义,与系统维护的真实映射不一致。
关联内容(自动生成)
- [/操作系统/linux/内核.html](/操作系统/linux/内核.html) Linux内核中的内存管理机制与虚拟内存概念密切相关,提供了对虚拟内存、地址空间等概念的具体实现
- [/操作系统/linux/Linux性能优化.html](/操作系统/linux/Linux性能优化.html) Linux性能优化中的内存管理部分与操作系统内存管理机制紧密相关,包括内存分配、回收、Swap机制等内容
- [/操作系统/虚拟化.html](/操作系统/虚拟化.html) 虚拟化场景下的内存管理涉及GVA→GPA→HPA的地址转换,是对传统内存管理在虚拟化环境中的扩展
- [/操作系统/安全.html](/操作系统/安全.html) 操作系统安全中的内存安全防护与内存管理机制紧密相关,包括地址空间布局随机化、内存访问权限控制等
- [/中间件/浏览器/V8.html](/中间件/浏览器/V8.html) V8引擎的内存管理和垃圾回收机制体现了高级语言运行时系统对底层内存管理的抽象和优化
- [/编程语言/JAVA/JVM/JVM.html](/编程语言/JAVA/JVM/JVM.html) JVM的内存管理机制(堆、栈、方法区等)是对操作系统内存管理的进一步抽象,体现了语言运行时的内存管理策略
- [/中间件/数据库/redis/Redis.html](/中间件/数据库/redis/Redis.html) Redis作为内存数据库,其内存管理策略、内存优化和内存分配机制与操作系统内存管理原理相通
- [/算法与数据结构/排序.html](/算法与数据结构/排序.html) 排序算法中的内存使用策略与操作系统内存管理中的页面置换算法在思想上有相似之处
- [/编程语言/C.html](/编程语言/C.html) C语言的内存模型和直接内存操作体现了操作系统内存管理的基本原理,包括堆栈管理、内存布局等
- [/操作系统/多处理机系统.html](/操作系统/多处理机系统.html) 多处理机系统中的内存一致性问题和NUMA架构与内存管理密切相关
- [/操作系统/输入输出.html](/操作系统/输入输出.html) 内存映射I/O机制是内存管理在I/O系统中的重要应用