存储系统

连接存储层次、地址翻译和数据访问,讲解字段计算、替换模拟、命中率与访问时间。

存储系统把程序产生的地址变成实际的数据访问。组原侧重 Cache、主存与访问时间,操作系统侧重地址空间、页表和页面置换;综合题经常把两边串起来。分清“地址翻译”和“数据访问”,才能知道每一次未命中究竟会引起什么操作。

这个板块包含哪些知识

存储系统图谱先讲层次,再展开一次访问。本页按这个关系组织:

  • 存储层次与局部性:寄存器、Cache、主存、外存的速度和容量关系,时间局部性与空间局部性。
  • Cache:映射与地址字段、有效位和标记、替换策略、写策略、命中率与缺失损失。
  • 虚拟存储:虚页和页框、单级与多级页表、TLB、保护与缺页处理。
  • 页面管理:驻留集、FIFO / LRU / CLOCK,以及访问序列引起的页面状态变化。

对一次典型访问,可以先沿 虚拟地址 → 地址翻译 → 物理地址 → Cache / 主存 追踪。TLB 缺失可能只需查页表,缺页才需要操作系统调页;Cache 缺失通常是从主存取块。三种事件的代价不能混算。

磁盘文件如何组织,另见文件系统与磁盘。

常见考点与题型

综合题可能组合下面几类小问。先看要求求什么,再确定需要调用哪些知识。

题型题干中的线索解题思路
地址字段与硬件容量容量、路数、块大小、页大小统一编址单位,先算块数或组数,再取位数;区分数据区与总容量
地址翻译与表项定位虚拟地址、页表基址、表项大小逐级提取索引并定位表项,取出页框号后拼接原偏移
Cache / 页面访问序列初态、替换策略、读写序列按次记录映射、命中和状态更新,必要时记录脏块写回
访问次数与平均时间TLB、Cache、主存、缺页代价先画题设串行或并行路径,再按各路径概率或实际次数累计
程序访问与局部性数组、循环顺序、步长把代码转换成地址序列,比较块内复用与组冲突,必要时逐次模拟

解题前要弄清的关系

地址类题可以先沿下面两条链定位问题;替换与性能题还需要记录访问序列、初态和各分支的代价。

一、地址翻译链:VA → PA 的实质是 VPN → PPN,页内偏移原样抄下来

  1. VA = 虚页号 VPN ‖ 页内偏移 —— 拆分点只由页大小决定,见 页面划分和地址结构
  2. VPN → TLB —— 一个装页表项的小 Cache,全相联或组相联;命中直接拿到 PPN,见 TLB
  3. VPN → 页表 —— 只在 TLB 缺失时走;多级则先页目录再页表,见 多级页表
  4. PA = 页框号 PPN ‖ 页内偏移(偏移位不变,可用于判断哪些索引位不必等待地址翻译)

二、Cache 访问链:PA → 数据,靠三段地址定位

  1. PA = 标记 Tag ‖ 组号 Index ‖ 块内地址 Offset —— 见 cache 地址结构
  2. 组号选中唯一一组 —— 直接映射是「组内一行」,n 路组相联是「组内 n 行」,全相联只有一组,见 cache 和主存映射方式
  3. 组内逐路比 Tag 并查有效位 —— 命中按 Offset 取字;缺失访主存调入整块
  4. 缺失后两件事:替换算法(LRU / FIFO / 随机)与写策略(写直达或写回,搭配题设的写分配或非写分配),见 替换算法、cache 写策略

两条链串起来就是一次完整访存,草稿上默画一遍,做题时只需往上填数:

虚拟地址 ─┬─ 虚页号 ─→ TLB ─命中→ 页框号
          │             └缺失→ 页表(多级先查页目录)─→ 页框号
          │                       └ 有效位 0 → 缺页异常 → 磁盘
          └─ 页内偏移 ──────────────────┐
                                        ↓
物理地址 = 页框号 ‖ 页内偏移
          ├─ 标记 + 组号 ─→ Cache ─命中→ 送 CPU
          └─ 块内地址              └缺失→ 访主存,调入整块

完整时序见 访存过程。

各类题的解法

地址计算先确定字段宽度,再代入地址;命中率、置换和时间题还要继续分析访问过程。

第一步:所有容量换算成位数

题干给的量直接推出关系
页大小页内偏移位数log₂(页大小)
主存块大小块内地址位数log₂(块大小)
Cache 数据区容量、路数、块大小组数、组号位数组数 = 容量 ÷ (路数 × 块大小)
物理地址位数标记位数物理地址位数 − 组号位数 − 块内地址位数
虚拟地址位数虚页号位数虚拟地址位数 − 页内偏移位数
页表基址、页表项大小页表项地址基址 + 表项号 × 表项大小

这张表填完,「占几位」「在哪一组」「页表项地址是多少」这几类小问就已经有答案了。会失分的情况通常是没填完就急着算下一问。

第二步:把链实例化

在草稿上重画那条链,把第一步算出的位数标在每一段上:虚页号几位、页内偏移几位、标记几位、组号几位。标出小问涉及的层次;组合题可能跨多个位置,先定位再计算,不要先套公式。

第三步:按问法对号入座

小问的问法落在链上哪一层固定动作
某虚拟地址的物理地址是多少页表页框号 × 页大小 + 页内偏移;位数对齐时直接拼接
页目录项 / 页表项的地址页表基址 + 表项号 × 表项大小,虚地址和物理地址各算一次
在 Cache 的哪一组 / 哪一行Cache取物理地址里的组号位段,不要用整个地址去除
命中率 / 缺失率Cache若从块边界顺序读完每块、每块仅首次缺失且无其他冲突,命中率为 (k−1)/k;一般情况按序列统计
平均访问时间Cache命中时间 + 缺失率 × 缺失损失
缺页次数页表无置换时按首次访问页数算;有置换时按完整访问序列模拟
按行还是按列遍历更快Cache先看步长和块内复用,再检查容量、映射冲突与初始状态

页表题常用两类计算:先用表项号定位页表项,再用页框号拼出物理地址。2013#46、2020#46 和 2024#45 是同一套题,其中 2024 年多绕一层——页表自己也放在某个页里,也要被翻译一次。

两种变形

以下“虚拟地址直接索引 Cache”讨论以题目明确采用 VIPT(Virtually Indexed, Physically Tagged)模型为前提;未说明时仍应按题设给出的访问顺序判断。

在上述 VIPT 模型中,让索引完全落在页内偏移中的条件是:组号位数 + 块内地址位数 ≤ 页内偏移位数。满足时这些位在虚拟地址和物理地址中完全相同,不必等地址转换结束就能开始索引 Cache。2011#44、2016#45 和 2019#46 靠它推理,2025#43 直接问「VA 中哪些位可以作为 Cache 索引」。

题干给了汇编或 C 代码,是把地址藏起来的写法,固定三步:

  1. 从代码里取数组首地址和元素大小,算出目标元素的虚拟地址;
  2. 把这个虚拟地址送进上面那条链;
  3. 遇到“哪种遍历顺序更好”,先比较步长与块内复用,再检查映射冲突。

会用到 汇编代码、数据对齐 和 大小端。

命中与替换:每次访问后更新状态

可以列“地址 / 页号或块号 / 组号 / 命中否 / 淘汰对象 / 更新后状态”六列。LRU 要在命中时更新最近使用次序,FIFO 的入队次序则不会因为命中改变;写回 Cache 淘汰脏块时,还要计入写回流量或时间。

例如两页框、初始为空,访问 A,B,A,C,B:LRU 在访问 C 时淘汰 B,最后访问 B 又缺页,共 4 次;FIFO 在访问 C 时淘汰 A,最后 B 仍在,共 3 次。先明确策略,再计数,不能只数不同页面。

平均时间:先区分“额外损失”和“总耗时”

若命中耗时 2 ns,缺失后额外花 50 ns,缺失率 10%,则平均时间为 2+0.1×50=7 ns。若题目说缺失访问从开始到完成共 50 ns,则应算 0.9×2+0.1×50=6.8 ns。

TLB 与 Cache 组合题也先列各分支实际经过的部件,再加权。只有题设允许并行的步骤才能取重叠时间,串行步骤需要相加。

历年题索引

框架和流程是通用的,下面这张表用于比较地址翻译、数据访问和状态变化的组合方式,练完一年再回上面对一遍流程。

真题主线这一年特别问了什么
2009#46请求分页 + TLB + LRU依次访问三个虚地址各需多少时间
2010#44Cache 直接映射行遍历与列遍历的命中率谁更高
2010#46分页 + FIFO / CLOCK同一个虚地址在两种置换算法下的物理地址
2011#44页表 + TLB 四路组相联 + Cache用物理地址访问 Cache 时的字段划分
2012#43Cache 缺失率 + 主存带宽由每秒缺失次数反推最低主存带宽
2012#45驻留集 + 空闲页框链表该置换策略是否适合时间局部性好的程序
2013#43Cache 块大小 + 突发传送读一个主存块需几次突发传送
2013#46二级页表页目录号与页表索引的表达式
2014#45指令 Cache + 缺页 + TLB哪条指令溢出、读磁盘与查 TLB 各几次
2015#46二级页表页目录加页表一共占多少页
2016#45TLB 全相联 + Cache 二路组相联为什么 Cache 可以直写而页面用回写
2017#45二级分页 + 机器指令取第 1 条指令时访问页目录与页表的第几项
2018#44TLB + Cache 回写TLB 用 SRAM 还是 DRAM、有效位的作用
2018#45二级页表 + 改进型 CLOCK由页目录号、页号、偏移反向合成虚拟地址
2019#46分页 + 指令 Cache 四路组相联call 指令只可能在哪一组命中
2020#44Cache 八路组相联 + 直写每行的 Tag 与 LRU 各几位、有没有修改位
2020#46二级页表 + 二维数组页目录项与页表项的物理地址
2021#44TLB 二路组相联 + LRU虚地址增到 32 位后表项要增加几位
2023#43请求调页 + Cache 四路组相联缺页次数与发生缺页的页故障地址
2024#44页式管理 + 汇编a[i] 所在页号、数组至少占几页
2024#45页表项定位页表所在页的页号及其页表项
2025#43Cache 八路组相联 + 缺页哪些 VA 位可作索引、平均访问时间
2025#46进程虚拟地址空间分区PCB、ptr、字符串常量各在哪个区域

易错清单

  • 组数忘了除路数。八路组相联的组数是「容量 ÷ 路数 ÷ 块大小」,少除一次路数,后面所有位数都错。
  • 按字编址和按字节编址混用。这只决定主存单元宽度,不能由它推寄存器宽度。
  • 不检查条件就用虚拟地址索引 Cache。见上面那一句不等式。
  • 把“首次装入”当成所有缺页题的规则。无置换时缺页次数才等于首次访问页数;出现 FIFO、LRU、CLOCK 或明确的置换后,必须逐次模拟,缺页次数可能超过数据占用页数。
  • 漏掉 TLB / Cache 初始为空造成的强制缺失。
  • 二级页表只做了一次乘加。定位页表项和拼物理地址是两步,不能合并。

上一页:数的表示与运算;下一页:CPU 与指令系统。