存储器层次结构

考点定位

  • 大纲章节:存储器分类与层次结构、主存储器、外部存储器(辅助存储器)、高速缓冲存储器(Cache)、虚拟存储器
  • 常见题型:本章是 408 计组大题第一热点(Cache 映射手推、芯片扩展连接几乎隔年一道大题),选择题密集(SRAM/DRAM、刷新、寻址计算、TLB、磁盘参数)
  • 考查频率:高(每年 6-10 分,Cache 一项常独占 4-8 分大题)
  • 前置知识:MAR/MDR 与编址见计算机系统概述,补码与定点数见数据的表示和运算
  • 工程师读者注意:你天天和内存、CPU 缓存打交道,但考试考的是地址位数的机械划分与芯片引脚的精确计算——不背套路,考场上现场推必然超时

一、存储器分类与层次结构

1.1 分类

按三个维度分类(选择题直接考归类):

分类维度类别
存储介质半导体存储器(TTL/MOS)、磁表面存储器(磁盘、磁带)、光存储器
存取方式随机存储器(RAM,SRAM/DRAM)、只读存储器(ROM)、串行访问存储器(顺序存取如磁带、直接存取如磁盘)
信息可保存性易失性(断电即失:RAM)与非易失性(ROM、磁盘);破坏性读出(DRAM 读后需再生)与非破坏性读出(SRAM)

易错口径:磁盘属"直接存取"存储器(先直接定位到小区域再顺序找),磁带才是"顺序存取"; Cache 与主存都是随机存取。

ROM 家族:MROM(掩膜)→ PROM(一次编程)→ EPROM(紫外线擦除)→ EEPROM(电擦除)→ Flash(闪存,块擦除,固态硬盘/BIOS)。Flash 写前必须先擦除、按块操作,这是选择题细节。

1.2 层次结构:两级映射

自上而下:速度更快、价格更高、容量更小。层次结构靠两个映射支撑:

层次解决的问题由谁管理对程序员
Cache—主存速度匹配硬件自动完全透明
主存—辅存容量匹配硬件 + 操作系统(虚拟存储器)对应用程序员透明(对系统程序员不透明)

记忆锚点:Cache—主存层次全靠硬件,所以快;主存—辅存层次靠 OS 介入(缺页要调磁盘),所以慢事件代价大。

1.3 局部性原理与定量分析

时间局部性:刚被访问过的项,很快会再次被访问(循环体、函数反复调用)。 空间局部性:刚被访问项的相邻项,很快会被访问(数组顺序遍历、指令顺序执行)。

定量工具(必背公式):

H=NcNc+NmH = \frac{N_c}{N_c + N_m}

其中 NcN_c 为访问 Cache 命中次数,NmN_m 为访问主存(未命中)次数。

平均访问时间(两种口径,看清题目假设):

  • 口径一(命中时不访主存,未命中才访):Ta=H⋅Tc+(1−H)(Tm)T_a = H \cdot T_c + (1-H)(T_m)
  • 口径二(先访 Cache,未命中再访主存,串行计入 Cache 时间):Ta=H⋅Tc+(1−H)(Tc+Tm)T_a = H \cdot T_c + (1-H)(T_c + T_m)

408 真题两种口径都出现过,题干会说"先访问 Cache,未命中再访问主存"(口径二)或"Cache 与主存同时访问"(口径一)。没说就默认口径二(多数教材口径)。

例:Tc=1 nsT_c = 1\ \text{ns},Tm=50 nsT_m = 50\ \text{ns},H=95%H = 95\%:口径二 Ta=0.95×1+0.05×51=3.5 nsT_a = 0.95\times1 + 0.05\times51 = 3.5\ \text{ns};口径一 Ta=0.95×1+0.05×50=3.45 nsT_a = 0.95\times1 + 0.05\times50 = 3.45\ \text{ns}。

访问效率 e=Tc/Tae = T_c / T_a(此题口径二下 e≈28.6%e \approx 28.6\%)。

二、主存储器

2.1 基本组成与编址

主存由存储体、地址译码驱动电路、读写电路组成,与 CPU 通过 MAR、MDR 交互(回顾计算机系统概述)。

编址口径:按字节编址(每单元 1 B)是默认;若按字编址需说明字长。容量题三件套:单元数 = 2MAR 位数2^{\text{MAR 位数}},总容量 = 单元数 × 每单元位数,地址空间 = 容量(按字节编址时)。

2.2 SRAM 与 DRAM(高频对比表)

对比项SRAM(触发器)DRAM(电容)
存储原理双稳态触发器电容存储电荷
是否刷新不需要必须刷新(电容漏电,典型 2 ms)
集成度低高(一位 1 管 1 容)
速度快慢
功耗大小
成本高低
地址引脚全部地址线行列地址分时复用,地址线减半(配合 RAS̅/CAS̅ 选通)
用途Cache主存

引脚复用细节:2n2^n 个单元的 DRAM 不引出 nn 根地址线,而是引 n/2n/2 根,先送行地址(RAS̅ 有效)再送列地址(CAS̅ 有效)。例:64M×8 位 DRAM,26 位地址只引 13 根地址线。选择题爱考"为什么 DRAM 芯片地址引脚是地址位数的一半"。

2.3 DRAM 刷新(必考小考点)

刷新三口径(以最大刷新间隔 2 ms、刷新以行为单位为前提):

方式做法特点
集中刷新2 ms 前正常读写,最后集中一段时间逐行刷新存在死时间(死区),期间不能读写
分散刷新每个存取周期拆成两半:前半读写 + 后半刷新一行无死区,但存取周期变长、整机速度下降
异步刷新2 ms 内把各行刷新间隔均匀分布(如 128 行 → 每 15.6 μs 刷一行)死时间分散成极短小段,是实际主流

必背结论:①刷新对 CPU 是透明的;②刷新按行进行,只需行地址;③刷新操作读出的是整行信息并再生,不需要片选。

2.4 存储芯片引脚与容量计算(套路化)

芯片规格写法"2n×m2^n \times m"表示 2n2^n 个单元、每单元 mm 位。引脚计算固定三步:

  1. 地址线:SRAM 引 nn 根;DRAM 引 n/2n/2 根(行列复用)
  2. 数据线:mm 根
  3. 控制线:SRAM 有片选 CS̅、读 OE̅/WE̅(读、写控制共 2-3 根);DRAM 用 RAS̅、CAS̅、WE̅(无片选,选通线兼任)

例题:SRAM 芯片 8K×8 位 → 地址线 log⁡28192=13\log_2 8192 = 13 根,数据线 8 根。DRAM 芯片 1M×4 位 → 地址 20 位 → 地址线 10 根,数据线 4 根。

反向题:给地址线与数据线反推容量。如某 DRAM 地址线 10 根、数据线 8 根 → 单元数 210×2=1M2^{10\times2} = 1\text{M},容量 1M×8 位 = 1 MB。

2.5 位扩展与字扩展(大题高频:芯片扩展连接)

  • 位扩展(加大字长):单元数够、位数不够。各芯片地址线、片选并联,数据线分段各接一段。
  • 字扩展(加大单元数):位数够、单元数不够。各芯片数据线并联,低位地址线共用,高位地址经译码器产生片选。

完整例题(手推全过程):用 4K×4 位 SRAM 芯片构成 16K×8 位主存模块。

第一步,算芯片数:字扩展 16K/4K=416\text{K}/4\text{K} = 4 倍,位扩展 8/4=28/4 = 2 倍,共 4×2=84\times2 = 8 片,分为 4 组、每组 2 片。

第二步,算地址线:系统地址 16K=21416\text{K} = 2^{14} → 14 根(A13A0);芯片地址 4K=2124\text{K} = 2^{12} → 12 根,接 A11A0。

第三步,算片选逻辑:高位 A13、A12 两位,接 2:4 译码器,4 路输出分别接 4 组芯片的 CS̅。

第四步,接数据线:每组 2 片位扩展——芯片 1 数据线接 D7D4,芯片 2 接 D3D0,两片共用同一片选与读写控制 WE̅/OE̅。

(映射与译码选择过程属动态内容,待动画化:高 2 位地址取值 → 译码器唯一输出有效 → 选通一组。)

地址空间分配表(考试可直接默画):

A13 A12选中组地址范围
0 0组 00000H ~ 0FFFH
0 1组 11000H ~ 1FFFH
1 0组 22000H ~ 2FFFH
1 1组 33000H ~ 3FFFH

易错提醒:地址范围写满 2142^{14} 空间;若系统还有其他部件,题目会给首地址,此时"首地址 + 芯片容量 − 1"才是末地址(进制加法别错)。

2.6 提高主存速度简要(选择考点)

  • 双端口存储器:两套独立端口(地址/数据/控制)并行读写;同时读同一单元允许,同时写同一单元或一读一写同一单元冲突。
  • 多体并行存储器:
    • 高位交叉编址(高位选体):顺序存储,一个体连续存满再下一个体,利于扩容,不能流水提速。
    • 低位交叉编址(低位选体):连续地址分布在不同体,可流水线方式并行存取。流水条件:体数 m≥T/rm \ge T/r(TT 为存取周期,rr 为总线传送周期)。例:T=4rT = 4r 则至少 4 个体,启动后每 rr 时间完成一个字的存取,带宽约提高 mm 倍。

三、程序访问局部性(大题视角)

综合题常给两段循环代码,问 Cache 行为差异。分析套路:

  1. 写出数据在主存中的存放顺序(C 数组行优先:a[i][j] 与 a[i][j+1] 相邻)
  2. 按执行顺序展开访问地址序列
  3. 按块大小分块,数出每块的命中/未命中

经典对比(设每行放 4 个 int,块大小 = 1 行缓存 4 个元素):

// 版本 A:按行访问 —— 空间局部性好
for (i = 0; i < N; i++)
    for (j = 0; j < N; j++)
        sum += a[i][j];

// 版本 B:按列访问 —— 空间局部性差
for (j = 0; j < N; j++)
    for (i = 0; i < N; i++)
        sum += a[i][j];

版本 A 每块首元素未命中、后 3 个命中(若 Cache 能容下若干行);版本 B 每次跨行访问,若整个数组装不进 Cache,几乎全部未命中。这就是"循环次序影响性能"的原理层解释,工程师直觉要落到地址序列上才得分。

指令本身也有局部性:循环体反复执行体现时间局部性,顺序取指体现空间局部性——所以指令 Cache 命中率通常高于数据 Cache。

四、高速缓冲存储器(Cache)

4.1 基本原理

Cache 全部由 SRAM 构成,由硬件完成全部映射与替换。核心概念:

  • 块(block):主存与 Cache 交换信息的最小单位,主存按块划分。
  • 行/槽(line/slot):Cache 中存放一个块及其信息的单元,行大小 = 块大小。
  • 每行附带标记(tag)(记录该行来自哪个主存块)与有效位(该行数据是否有效,开机时全部无效)。

CPU 给出主存地址 → 按映射规则定位到候选行 → 比较标记与有效位 → 命中则直接取数;未命中则从主存调入块,必要时替换旧行。

4.2 三种映射方式(本章核心,必会手推)

设主存地址共 nn 位、块大小 2b2^b 字节、Cache 共 2c2^c 行。

4.2.1 直接映射:一行对一块,唯一去处

Cache 行号=主存块号 mod 2c\text{Cache 行号} = \text{主存块号} \bmod 2^c

地址划分:标记 (n−b−c)(n-b-c) 位 | 行号 cc 位 | 块内地址 bb 位

特点:硬件最简单、速度快;但冲突多(两个常用块映射到同一行会互相踢),利用率低。直接映射不需要替换算法(候选行唯一)。

4.2.2 全相联:任何块可放任何行

地址划分:标记 (n−b)(n-b) 位 | 块内地址 bb 位(标记 = 主存块号)。

查找:主存块号与 Cache 所有行的标记同时比较(相联存储器,按内容并行查找)。灵活性最好、冲突最少;但标记比较电路代价大,只适合小容量 Cache(如 TLB 常用全相联/组相联)。需要替换算法。

4.2.3 组相联:组间直接、组内全相联(现代 CPU 通用)

Cache 组号=主存块号 mod 2g\text{Cache 组号} = \text{主存块号} \bmod 2^{g}

地址划分:标记 (n−b−g)(n-b-g) 位 | 组号 gg 位 | 块内地址 bb 位

先按组号直接定位唯一组,再在组内 rr 路中全相联查找与替换(rr 路组相联 = 每组 rr 行,总行数 2g×r2^g \times r)。r=1r=1 退化为直接映射,r=2cr=2^c 退化为全相联——选择题问"某映射方式可否视为另一种的特例"就是考这个。

4.2.4 表格化手推样例(背下这个流程,大题直接套)

题目设定:主存 1 MB(20 位地址),Cache 数据容量 8 KB,块 32 B。

第一步(分参数):

参数计算结果
块内地址位数 bblog⁡232\log_2 325 位
Cache 行数8K/32=256=288\text{K}/32 = 256 = 2^8256 行,c=8c = 8
(2 路组相联时)组数256/2=128=27256/2 = 128 = 2^7g=7g = 7

第二步(地址划分对照):

映射方式地址划分(高位→低位)标记位数
直接映射标记 7 位 | 行号 8 位 | 块内 5 位7
2 路组相联标记 8 位 | 组号 7 位 | 块内 5 位8
全相联标记 15 位 | 块内 5 位15

第三步(给定地址逐位拆解):主存地址 0x35C4A,二进制 20 位:

0011010⏟直接映射标记 11100010⏟行号/组号部分 01010⏟块内地址\underbrace{0011010}_{直接映射标记}\ \underbrace{11100010}_{行号/组号部分}\ \underbrace{01010}_{块内地址}

映射方式标记定位块内偏移
直接映射0011010(26)第 11100010 行 = 226 行01010(10)
2 路组相联00110101(0x35)第 1100010 组 = 98 组(组内 2 路任一)01010
全相联001101011100010(块号 6882)任意行01010

验算(防错关键):块号 = 0x35C4A≫5=68820x35C4A \gg 5 = 6882;直接映射行号 = 6882 mod 256=2266882 \bmod 256 = 226 ✓;组号 = 6882 mod 128=986882 \bmod 128 = 98 ✓。位拆法与模运算法互验,大题强烈建议双算一遍。

第四步(命中判断):第 226 行(或第 98 组)有效位 = 1 且标记字段 = 0011010 → 命中,按块内偏移 10 取出数据;否则未命中,从主存第 6882 块调入。

(上述逐位拆解与查找过程可在交互演示中输入任意地址逐步验证:切换映射方式,观察标记/组号/偏移的位级划分。)

4.3 替换算法(未命中且候选行已满时)

算法规则特点/坑
RAND 随机随机换出一行硬件最简单,没利用局部性
FIFO 先进先出换出最早调入的行实现"在"时间,与访问频率无关;有 Belady 异常(容量增大命中率反降)
LRU 最近最少使用换出最久未被访问的行命中率最接近 OPT(最优算法,换出以后最久不用的,仅理论对照);实现要计数器/栈;Cache 中最常考

LRU 手推套路:维护一个从新到旧的访问序列,命中时该块提到队首,未命中时淘汰队尾。组相联只需在组内维护该序列。

Belady 异常只属于 FIFO(及随机类不利用栈性质的算法),LRU 与 OPT 不会出现——高频判断题。

4.4 写策略(写命中与写未命中两问分开答)

写命中(Cache 与主存都有该块):

  • 写直达(write-through):同时写 Cache 与主存。可靠、实现简单;写速度受主存拖累(常用写缓冲缓冲)。
  • 写回(write-back):只写 Cache,置脏位(修改位);该行被替换时才写回主存。速度快,但有一致性风险,硬件需脏位。

写未命中(主存有、Cache 无):

  • 写分配(write-allocate):先把块调入 Cache 再写。习惯与写回配对。
  • 非写分配(no-write-allocate / write-around):直接写主存,不调入。习惯与写直达配对。

选择题高频:"写回法通常配合写分配法""写直达法通常配合非写分配法",问原因:写回本来就指望后续再写同一块,值得调入;写直达每次都同步主存,调入意义小。

多级 Cache 一致性:各级之间也用写直达/写回(如 L1 写直达到 L2,L2 写回到主存)。

4.5 Cache 命中率与平均访问时间

H=命中次数总访问次数,Ta=H⋅Tc+(1−H)(Tc+Tm) (串行口径)H = \frac{\text{命中次数}}{\text{总访问次数}},\quad T_a = H\cdot T_c + (1-H)(T_c + T_m)\ \text{(串行口径)}

大题流程:展开访问序列 → 按映射方式算每次命中与否(首次访问某块必未命中)→ 数命中率 → 代公式。

Cache 总容量计算(含开销,大题必背):

Cache 总位数=行数×(块数据位+标记位+有效位+脏位+替换算法位)\text{Cache 总位数} = \text{行数} \times \left(\text{块数据位} + \text{标记位} + \text{有效位} + \text{脏位} + \text{替换算法位}\right)

替换算法位:2 路组相联 LRU 每行 1 位;rr 路需 log⁡2r\log_2 r 位/行;直接映射与随机替换为 0。

例(接 4.2.4 设定,写回 + LRU 2 路组相联):每行开销 = 32×8+8+1+1+1=26732\times8 + 8 + 1 + 1 + 1 = 267 位,总容量 = 256×267=68352256 \times 267 = 68352 位 = 8544 B。

4.6 Cache 行与主存块对应的手推题套路(大题模板)

标准题干:"主存 X 位地址 / Cache 多大 / 块多大 / 某映射方式,给一串访问地址,问命中情况与命中率。"作答四步:

  1. 算 bb、cc(或 gg),写出地址划分与标记位数(先把这张表画在答卷上,后面反复用)
  2. 对每个访问地址算块号 → 行号/组号(用  mod \bmod 验算位拆结果)
  3. 维护"行号 → 标记(主存块号)"状态表,逐个访问判定命中/替换(LRU 顺序随时更新)
  4. 统计命中率,如问时间再代入 TaT_a 公式

状态表示例(直接映射,沿用 4.2.4 设定,访问块序列 6882, 1030, 6882, 4126, 1030):

访问序块号行号(块号 mod 256)行内原标记结果
16882226—未命中,装入,标记=26
210306—未命中,装入
3688222626命中
441264126 = 16×256 + 30 → 行 30行 30 为空未命中,装入,标记=16
510306块 1030 的标记命中

注意第 4 步演示的坑:4126 mod 256=304126 \bmod 256 = 30 要老老实实算(4126=16×256+304126 = 16 \times 256 + 30),块号大不能想当然;注意 4126 与 6882 不映射到同一行(226 ≠ 30),二者互不冲突;状态表才是判命中的唯一依据,不能凭"访问过"判断。

五、虚拟存储器

5.1 页式虚拟存储器(工作过程必背)

主存—辅存层次对应用程序员呈现为"虚拟地址空间"。页式虚拟存储器把虚存空间与主存空间都划成固定大小的页(典型 4 KB):

  • 虚拟地址(VA)= 虚页号(高位)+ 页内偏移(低位)。例:32 位 VA、4 KB 页 → 虚页号 20 位 + 偏移 12 位。
  • 页表:每个进程一张,驻留主存,页表项记录"虚页号 → 实页框号(物理页号)+ 有效位 + 修改位 + 访问位 + 保护位"。页内偏移在虚实转换中不变。
  • 地址转换:VA → 查页表(页表基址寄存器 + 虚页号 × 页表项长度)→ 得实页框号 → 拼 页框号 | 页内偏移 = 物理地址(PA)。
  • 页表项有效位 = 0 → 缺页(页故障):由 OS 缺页处理程序从磁盘调入(可能触发页面替换),属内中断(故障 fault),处理后重新执行该指令。
  • 快表 TLB(见 5.2)加速地址转换。

5.2 TLB(快表)

页表在主存 → 每次取数要多一次访存。TLB 是页表项的小 Cache(SRAM,相联存储器,常为全相联或组相联):

  • TLB 内容:页表项的副本(虚页号标记 + 实页框号 + 有效/修改/保护位)。
  • 查找:虚页号与 TLB 标记比较(组相联:虚地址的"TLB 组号"位先定位组)→ 命中直接得页框号,不再查页表。
  • TLB 缺失 → 查页表:页表命中则把该页表项装入 TLB(TLB 满则按 LRU 替换,被替换项若修改位为 1 要写回页表);页表也缺失才缺页中断。

(TLB→页表→Cache 三级查找为动态内容,待动画化。)

5.3 TLB、页表与 Cache 的访问层次与时间计算

三个部件的容量关系常考:TLB 最小最快(几十至几百项)→ Cache(KB~MB 级)→ 主存/页表(GB 级)→ 磁盘。TLB 与 Cache 都是主存的"缓存",但缓存对象不同:TLB 缓存页表项,Cache 缓存主存块——两者可以同时命中或一齐缺失。

时间计算(分层概率模型,大题模板)。设:TLB 访问时间 tt、主存访问周期 TmT_m、Cache 访问时间 TcT_c,TLB 命中率 HtH_t,Cache 命中率 HcH_c,忽略缺页(概率极小):

Ta=Ht⋅(t+TCache)⏟TLB 命中+(1−Ht)⋅(t+Tm+TCache)⏟TLB 缺失需访页表T_a = \underbrace{H_t \cdot (t + T_{\text{Cache}})}_{\text{TLB 命中}} + \underbrace{(1-H_t) \cdot (t + T_m + T_{\text{Cache}})}_{\text{TLB 缺失需访页表}}

其中 TCache=HcTc+(1−Hc)(Tc+Tm)T_{\text{Cache}} = H_c T_c + (1-H_c)(T_c + T_m)。

分步拆解:①TLB 命中:tt + 访 Cache;②TLB 缺失、页表命中:tt + 访主存查页表 TmT_m + 访 Cache;③页表缺失:加缺页代价(百万周期级,通常题目让你忽略或单列)。把每种路径的时间与概率列成表再加权求和,是大题标准作答格式。

5.4 段式与段页式(对比即可,考选择)

对比项页式段式段页式
划分单位固定大小页(硬件视角,对用户透明)按程序逻辑(函数/数组/模块),长度可变先分段,段内再分页
地址构成虚页号 + 页内偏移段号 + 段内偏移段号 + 段内页号 + 页内偏移
优缺点无外碎片、有内碎片;管理简单便于共享保护、无内碎片;有外碎片、管理复杂二者折中,需三次查表(段表→页表→主存)
表每进程一张页表每进程一张段表(每段一项:基址+长度)段表 + 每段一张页表

段式地址越界判断:段内偏移 ≥ 段长 → 越界中断(地址转换中的保护检查,高频选择)。

六、辅助存储器(磁盘,按 408 大纲简要)

6.1 磁盘结构与参数

  • 盘面(磁头)→ 磁道(每面同心圆)→ 扇区(最小读写单位,通常 512 B);所有盘面同半径磁道构成柱面。
  • 地址三件套:柱面(磁道)号、盘面(磁头)号、扇区号。
  • 容量 = 盘面数 × 每面磁道数 × 每道扇区数 × 每扇区字节数。区分非格式化容量(按位密度理论值,更大)与格式化容量(按扇区,实际可用,更小)。
  • 磁盘存取速度三指标:寻道时间(磁头移到目标磁道)、旋转延迟(目标扇区转到磁头下,平均 = 半转时间)、传输时间(读写数据本身)。

6.2 访问时间计算

T访问=T寻道+T旋转延迟+T传输T_{\text{访问}} = T_{\text{寻道}} + T_{\text{旋转延迟}} + T_{\text{传输}}

  • 平均旋转延迟 = 12×60转速(rpm) s\dfrac{1}{2} \times \dfrac{60}{\text{转速(rpm)}}\ \text{s}。速算:7200 rpm → 每转 8.33 ms → 平均 4.17 ms;10000 rpm → 每转 6 ms → 平均 3 ms。
  • 传输时间 = 读写字节数转速×每磁道字节数\dfrac{\text{读写字节数}}{\text{转速} \times \text{每磁道字节数}}(转一圈传一道)。

例:转速 10000 rpm,每道 400 扇区 × 512 B,寻道 6 ms,读一个扇区:旋转延迟 3 ms;每转 6 ms 传一道,一个扇区传输 6/400=0.0156/400 = 0.015 ms;总计 6+3+0.015=9.0156 + 3 + 0.015 = 9.015 ms——注意传输时间往往小到可忽略,大头是寻道与旋转。

RAID 简要:RAID 0 条带化提速不冗余、RAID 1 镜像、RAID 5 分布式校验,选择考概念级别即可。

例题

例题 1(模拟题) 某计算机主存按字节编址,地址 32 位,Cache 数据容量 32 KB,块大小 64 B,2 路组相联。(1) 写出主存地址划分;(2) 求标记位数;(3) 采用写回法 + LRU,求每行总开销位数。

解:(1) 块内 log⁡264=6\log_2 64 = 6 位;行数 32K/64=51232\text{K}/64 = 512,2 路组相联 → 组数 256=28256 = 2^8 → 组号 8 位;标记 =32−8−6=18= 32-8-6 = 18 位。地址 = 标记 18 | 组号 8 | 块内 6。(3) 每行开销 = 标记 18 + 有效 1 + 脏 1 + LRU log⁡22=1\log_2 2 = 1 = 21 位。

例题 2(模拟题) 直接映射 Cache,主存 16 位地址,Cache 4 KB,块 16 B。问主存地址 0x1234 映射到哪一行,标记是多少?

解:块内 4 位,行数 4K/16=256=284\text{K}/16 = 256 = 2^8 → 行号 8 位,标记 16−8−4=416-8-4 = 4 位。0x1234=0001 0010 0011 01000x1234 = 0001\,0010\,0011\,0100:标记 0001,行号 0010 0011(35 行),块内 0100。验算:块号 =0x1234≫4=0x123=291= 0x1234 \gg 4 = 0x123 = 291,291 mod 256=35291 \bmod 256 = 35 ✓。

例题 3(模拟题) 用 1K×4 位芯片组成 4K×8 位存储器,需要几片?片选需几位地址译码?

解:字扩展 4 倍、位扩展 2 倍,共 8 片。芯片地址 10 根接 A9~A0,高位 A11A10 共 2 位经 2:4 译码器产生 4 个片选。

例题 4(模拟题) 某程序对某数据结构共访问 1000 次,950 次命中 Cache。Cache 周期 2 ns,主存周期 40 ns,先访问 Cache 未命中再访主存。求命中率与平均访问时间。

解:H=950/1000=95%H = 950/1000 = 95\%;Ta=0.95×2+0.05×(2+40)=1.9+2.1=4.0T_a = 0.95\times2 + 0.05\times(2+40) = 1.9 + 2.1 = 4.0 ns。

例题 5(模拟题) 关于 DRAM 刷新,下列说法错误的是( )。 A. 刷新以行为单位 B. 刷新对 CPU 透明 C. 集中刷新没有死时间 D. 异步刷新将死时间分散

解:C。集中刷新在刷新期间不能读写,存在死时间(死区);分散刷新才无死区。

例题 6(模拟题) 虚拟地址 32 位,页大小 4 KB,TLB 命中率 99%,TLB 访问 1 ns,查页表(访主存)50 ns,随后访 Cache 命中率 90%,Cache 5 ns,未命中加 50 ns 主存。忽略缺页,求一次取数平均时间。

解:访 Cache 时间 =0.9×5+0.1×(5+50)=10= 0.9\times5 + 0.1\times(5+50) = 10 ns。地址转换 =0.99×1+0.01×(1+50)=0.99+0.51=1.5= 0.99\times1 + 0.01\times(1+50) = 0.99+0.51 = 1.5 ns。总计 Ta=1.5+10=11.5T_a = 1.5 + 10 = 11.5 ns。

常见坑

  1. 命中率公式分母是总访问次数,不是主存访问次数;平均访问时间注意题目是"同时访问"还是"先 Cache 后主存"两种口径。
  2. 直接映射不需要替换算法;只有全相联与组相联的组内才需要。
  3. 标记位数随映射方式变化:全相联 > 组相联 > 直接映射(同一容量下),别套错。
  4. Cache 总容量大题必须加标记位、有效位(+ 脏位 + LRU 位),只算数据位是高频扣分点。
  5. LRU 看"最近是否访问",FIFO 看"进入时间"——命中也会更新 LRU 顺序,但不影响 FIFO 队列。
  6. 写回配写分配、写直达配非写分配,选项交叉配对必错。
  7. DRAM 地址引脚是地址位数的一半(行列复用);DRAM 有 RAS̅/CAS̅,没有常规 CS̅。
  8. 低位交叉编址流水条件体数 ≥T/r\ge T/r;高位交叉不能提速。
  9. TLB 命中就不再查页表;TLB 缺失不等于缺页(页表多数仍命中),缺页是页表有效位为 0。
  10. 页内偏移虚实不变,变的是高位页号部分;段式才有"越界中断",页式没有(页号合法即可)。
  11. 磁盘平均旋转延迟 = 半转时间;传输时间 = 数据量占整道的比例 × 每转时间。
  12. 双端口存储器"同时读同一单元"不冲突,"一读一写或双写同一单元"冲突。

自测

  1. 主存 32 位地址、按字节编址,Cache 64 KB、块 128 B,直接映射。求地址划分与标记位数。
  2. 某 DRAM 芯片容量 16M×8 位,地址引脚与数据引脚各多少根?
  3. 写回法为什么需要脏位?写直达法为什么常配写缓冲?
  4. 2 路组相联 Cache 共 64 行,访问序列为块 5, 8, 5, 133, 8。写出每次命中情况(每组 32 组)。
  5. 转速 5400 rpm 的磁盘,平均旋转延迟约多少毫秒?寻道 8 ms、读半道数据的传输时间(每转读写一道计)是多少?
  6. TLB 缺失、页表命中时,地址转换共发生几次访存(不含最终取数,TLB 与页表访问均计)?

自测答案与简析

  1. 块内 7 位;行数 64K/128=512=2964\text{K}/128 = 512 = 2^9 → 行号 9 位;标记 =32−9−7=16= 32-9-7 = 16 位。
  2. 地址 24 位 → 地址引脚 12 根(行列复用);数据引脚 8 根。
  3. 写回:只写 Cache,脏位标记该行被改过,替换时仅把脏行写回主存,避免无谓写回。写直达:每次写都同步主存,写慢,用写缓冲让 CPU 不必等主存写完。
  4. 组号 = 块号 mod 32:块 5 → 组 5;块 8 → 组 8;块 133 → 133 mod 32=5133\bmod32 = 5 → 组 5。序列:5 未命中装入组 5;8 未命中装入组 8;5 命中(更新 LRU);133 映射到组 5,该组 2 路只占了 1 路(块 5),尚有空位,未命中但无需淘汰,直接装入;8 命中。共 2 次命中,命中率 40%。错因提醒:看见"同组"就急着替换是高频错误——先看组内是否还有空行。
  5. 每转 60/5400≈11.1160/5400 \approx 11.11 ms,平均旋转延迟 ≈5.56\approx 5.56 ms;半道传输 =11.11/2≈5.56= 11.11/2 \approx 5.56 ms;总 ≈8+5.56+5.56≈19.1\approx 8+5.56+5.56 \approx 19.1 ms。
  6. 1 次主存访问(读页表)。TLB 是 CPU 内 SRAM 部件,其访问不占主存访存周期;若题目口径把 TLB 访问也计入"访存",才需要加上。