1.7.2 层次化存储
本节导学:存储系统的本质是速度、容量、成本三者之间的工程妥协
课程从买电脑的直觉讲起:硬盘常见 500GB、1TB,内存常见 8GB、16GB,而 CPU 寄存器的容量小到几乎不会被普通用户拿来比较。为什么不把所有存储都做成寄存器那样快?因为太贵、太小、工艺和功耗都不现实。为什么不只用硬盘?因为 CPU 等不起。
层次化存储就是在这组矛盾里找到工程平衡:让最常用的数据靠近 CPU,让大量但不常用的数据放在更便宜、更大的层次。
1. 存储金字塔
这张图是本节最高频考点。题目只要问“越靠近 CPU 的存储器有什么特点”,就抓三句话:更快、更小、更贵。
2. 为什么不能只用一种存储器
| 假设方案 | 看似优点 | 致命问题 | 工程结论 |
|---|---|---|---|
| 全部用寄存器/高速 SRAM | CPU 访问极快 | 成本极高,容量极小,无法保存大量程序和数据 | 只能放 CPU 最急需的一小部分数据 |
| 全部用主存 DRAM | 容量比寄存器大,成本较低 | 速度仍远低于 CPU,处理器大量等待 | 需要 Cache 缓解速度差 |
| 全部用外存 | 容量大,断电可保存,单位成本低 | 访问延迟太高,不能直接支撑 CPU 运算 | 适合长期保存,不适合作为直接工作区 |
层次化存储不是为了“把旧技术淘汰掉”,而是让不同存储技术各自放在最适合的位置。寄存器、Cache、主存、外存不是互相替代关系,而是协作关系。
3. 技术迭代:为什么会出现 Cache 和虚拟存储
| 技术问题 | 旧方案 | 旧方案优点 | 旧方案缺陷 | 新方案 | 新方案代价 |
|---|---|---|---|---|---|
| CPU 比主存快太多 | CPU 直接访问主存 | 结构简单 | CPU 经常等待主存,吞吐下降 | 在 CPU 与主存之间加入 Cache | 需要命中判断、替换策略、一致性维护 |
| 主存容量不够 | 程序必须完全装入主存 | 管理简单,访问直接 | 大程序或多程序运行受限 | 用主存 + 外存构成虚拟存储 | 缺页时访问外存很慢,需要页表和调度 |
| 外存机械硬盘延迟高 | HDD 保存长期数据 | 容量大、便宜 | 随机访问慢、机械结构限制明显 | SSD/NVMe 等固态存储 | 单位成本、写入寿命和控制器复杂度要权衡 |
学习时要把 Cache 和虚拟存储分开:Cache 主要解决速度差,虚拟存储主要解决容量表象。
4. Cache 的位置与工作方式
Cache 位于 CPU 和主存之间,里面保存的是主存中一部分内容的副本。
CPU 访问数据时,一般先查 Cache:命中就直接从 Cache 取,未命中再访问主存,并可能把相应块调入 Cache,再供 CPU 使用。这个过程已经画在上方流程图里。
Cache 能有效,不是因为它容量大,而是因为程序访问有局部性。它赌的是“刚用过的还会再用”和“刚用到某个地址,附近地址也快要用到”。
5. 局部性原理:缓存能生效的理论基础
| 类型 | 课程里的核心表述 | 程序例子 | 对 Cache 的意义 |
|---|---|---|---|
| 时间局部性 | 刚被访问过的内容,在不久后可能再次被访问 | 循环体中的指令、反复使用的变量 | 最近访问过的数据留在 Cache,后续容易命中 |
| 空间局部性 | 访问某个存储单元后,附近单元可能很快被访问 | 顺序执行指令、遍历数组 A[0] 到 A[100] | 调入一整块数据,而不是只调一个字节 |
判断题干时抓关键词:
“刚访问过,不久又访问” → 时间局部性
“相邻地址、连续区域、顺序访问” → 空间局部性如果程序访问完全随机,Cache 命中率会下降,层次化存储的平均访问优势也会变弱。
6. 主存、外存、RAM、ROM 的边界
课程里常把这些概念放在一起考,建议按“是否直接参与运行、是否断电丢失、是否可写”区分。
| 名称 | 常见含义 | 断电后 | 典型用途 | 易混点 |
|---|---|---|---|---|
| 主存/内存 | CPU 可直接编址访问的运行时存储 | RAM 部分通常丢失 | 运行程序、保存当前数据 | 不是长期保存资料的地方 |
| RAM | 随机存取存储器,可读可写 | 通常易失 | 内存条 | “随机存取”不是随机内容,而是可直接按地址访问 |
| ROM | 只读存储器或以读为主的固化存储 | 通常不丢失 | BIOS/固件等 | 名称是只读,但现代实现可能可擦写 |
| 外存/辅存 | 硬盘、SSD、U盘、光盘等 | 不丢失 | 长期保存文件 | 容量大但比主存慢 |
BIOS 这类固件常放在 ROM 或类似非易失存储中,原因是开机时必须先有一段稳定存在的启动程序。
7. 虚拟存储:用主存和外存共同制造“大内存”的假象
虚拟存储不是 Cache。它的两级结构是:
主存 + 外存程序看到的是一个较大的虚拟地址空间,操作系统和硬件负责把当前需要的部分放在主存,不常用的部分放在外存。主存不够时,通过换入、换出维持运行。
虚拟存储的地址转换和缺页调入过程也画在上面的流程图下半部分:程序发出虚拟地址,经过页表/MMU 转换;若主存中已有页面就直接访问,若缺页就从外存调入页面。
它的优势是让程序不必完全受物理内存容量限制,也便于多程序隔离;代价是缺页时要访问外存,速度会急剧下降。频繁缺页会导致系统大量时间花在换页上,程序反而变慢。
8. Cache 与虚拟存储的对比
| 对比项 | Cache | 虚拟存储 |
|---|---|---|
| 解决的核心问题 | CPU 与主存速度不匹配 | 主存容量不够、地址空间管理 |
| 典型层次 | Cache + 主存 | 主存 + 外存 |
| 数据单位 | 块/Cache line | 页/段页 |
| 依赖基础 | 时间局部性、空间局部性 | 局部性 + 操作系统调度 |
| 对程序员是否透明 | 通常透明 | 通常透明,但性能会受缺页影响 |
| 考试陷阱 | 误以为 Cache 是扩大内存容量 | 误以为虚拟存储是 Cache + 主存 |
一句话记忆:Cache 是“让常用数据更快”,虚拟存储是“让可用空间看起来更大”。
9. 本节考点地图
| 题型 | 题干信号 | 解题动作 |
|---|---|---|
| 三要素方向 | “越靠近 CPU...” | 速度更快,容量更小,单位成本更高 |
| Cache 位置 | “CPU 与主存之间” | 选 Cache |
| 局部性判断 | “刚访问过又访问” | 时间局部性 |
| 局部性判断 | “相邻地址、连续存储区域” | 空间局部性 |
| 虚拟存储组成 | “虚拟存储由哪两级组成” | 主存 + 外存 |
| 技术取舍 | “为什么采用层次化” | 单一存储无法同时满足速度、容量、成本 |
🧪 例题(按难度)
简单(3题)
中级(3题)
例题1(局部性判断)
“CPU 访问存储器时,被访问数据一般会聚集在一个较小的连续存储区域中;若一个存储单元已被访问,那么相邻的存储单元很有可能被访问。”
该描述体现的是:
例题2(虚拟存储的组成)
虚拟存储体系通常由哪两级存储结构组成?
困难(1题)
for (int i = 0; i < n; i++) sum += a[i]; // 顺序访问数组
for (int t = 0; t < 100; t++) do_work(); // 循环反复执行上述场景分别体现了哪些局部性原理?(可多选)
📚 本课小结
- 层次化存储:速度/容量/成本的权衡
- 局部性原理:时间局部性、空间局部性
- 虚拟存储:主存 + 外存