四、存储系统与Cache:主存与辅存、Cache工作原理、地址映射方式、替换算法、虚拟存储器基础

存储系统是计算机体系结构的核心支柱之一。在国网计算机类考试中,本章不仅考查基本概念,更注重对Cache地址映射、替换算法以及虚拟存储器地址变换过程的深入理解。考生需要建立“容量-速度-成本”的权衡视角,掌握从辅存到主存、再从主存到Cache的多级存储层次如何协同工作。以下从五个核心模块展开讲解。

存储层次与Cache-虚拟存储器协同工作架构 CPU寄存器 容量: 数百B | 速度: 1ns Cache(SRAM) 容量: 32KB~数MB | 速度: 2~10ns 地址映射: 全相联/直接/组相联 主存(DRAM) 容量: 4GB~64GB | 速度: 50~100ns 按字节/字编址,与Cache以块为单位交换 辅存(SSD/HDD) 容量: 512GB~数TB | 速度: 0.1~10ms 虚拟存储器:主存+辅存构成统一逻辑空间 虚拟存储器 逻辑地址 → 物理地址 页表/段表 + TLB 缺页中断 → 辅存调入 页面置换算法 LRU / FIFO / Clock Cache替换算法 随机法(RAND) 先进先出(FIFO) LRU(近期最少使用) LFU(最不经常使用) 命中率对比与硬件开销 平均访问时间 = 命中率 × Cache访问时间 + (1-命中率) × 主存访问时间 系统性能 = f(命中率, 层次间带宽, 替换策略, 块大小)

4.1 主存与辅存:存储层次的基础架构

4.1.1 核心原理:为什么需要多级存储

计算机系统对存储器的要求是“大容量、高速度、低成本”,但三者相互制约。SRAM速度最快但价格昂贵,DRAM容量较大但速度慢于SRAM,辅存(SSD/HDD)容量最大但速度最慢。因此现代计算机采用层次化存储结构:CPU寄存器→Cache→主存→辅存,每一层都作为下一层的缓存,利用局部性原理(时间局部性和空间局部性)提升整体性能。

存储层次典型介质容量范围访问时间价格/GBCPU直接访问
寄存器触发器数百B~1ns极高是
CacheSRAM32KB~数MB2~10ns高是
主存DRAM4GB~64GB50~100ns中是
辅存SSD/HDD512GB~数TB0.1~10ms低否(需先调入主存)

4.1.2 判断方法:主存与辅存的分工

  • 主存(内存):CPU可直接通过地址总线访问,存放当前运行的程序和数据,断电后数据丢失(DRAM易失性)。
  • 辅存(外存):CPU不能直接访问,必须通过DMA或中断方式将数据块调入主存后才能被CPU读取,断电后数据保留(非易失性)。
  • 数据交换单位:主存与Cache之间以“块”(Block/Line)为单位,通常为16~128字节;主存与辅存之间以“页”(Page)或“段”为单位,通常为4KB~64KB。
考试提示:主存与辅存的核心区别在于“CPU是否可直接访问”和“数据是否易失”。辅存不能直接与CPU交换数据,必须经过主存中转,这是虚拟存储器设计的前提。

4.1.3 案例拆解:程序运行时的数据流动

假设用户双击打开一个存放在SSD中的Word文档:

  1. CPU发出读请求,操作系统通过文件系统定位文档在SSD中的逻辑地址;
  2. SSD中的数据以页为单位(如4KB)通过DMA控制器拷贝到主存的用户缓冲区;
  3. CPU访问主存中的文档数据时,Cache控制器将数据块(如64B)从主存调入Cache;
  4. 后续CPU对同一文档区域的读写操作直接命中Cache,无需再次访问主存。

整个过程体现了“辅存→主存→Cache→寄存器”的逐级搬运,每一级都通过预取和缓存策略减少下一级的访问频率。

4.1.4 常见误区与复盘

误区1:认为CPU可以直接访问辅存。实际上CPU发出的地址是逻辑地址/虚拟地址,必须经过MMU(内存管理单元)转换为物理地址,若目标数据不在主存中,则触发缺页中断,由操作系统从辅存调入。
误区2:混淆“主存容量”与“虚拟内存容量”。虚拟内存是主存+辅存的一部分(页面文件/交换分区)共同构成的逻辑空间,其容量可远超物理主存。

4.2 Cache工作原理:命中与缺失的判定

4.2.1 核心原理:Cache如何工作

Cache位于CPU与主存之间,由SRAM构成,保存主存中部分数据的副本。CPU访问存储器时,先检查Cache:

  • 命中(Hit):所需数据在Cache中,直接返回,访问时间为Cache访问时间(如2ns)。
  • 缺失(Miss):所需数据不在Cache中,需从主存读取该数据块(同时包含目标字),将其装入Cache,并返回给CPU。若Cache已满,则按替换算法淘汰一个旧块。

衡量Cache性能的关键指标是命中率H,平均访问时间公式为:

平均访问时间 = H × T_cache + (1-H) × (T_miss_penalty)
其中 T_miss_penalty = T_memory + T_cache_update

4.2.2 判断方法:Cache缺失的三种类型(3C模型)

缺失类型产生原因减少方法
强制缺失(Compulsory)首次访问某块数据,Cache中必然不存在增大块大小(预取更多相邻数据)
容量缺失(Capacity)Cache容量不足,无法容纳程序工作集增大Cache容量
冲突缺失(Conflict)多个地址映射到同一Cache行,互相淘汰提高相联度(组相联/全相联)

4.2.3 案例拆解:命中率计算

某程序访问序列(按块号):1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5。Cache容量为4块,采用LRU替换。计算命中率:

  1. 访问1(缺失,装入1)→ 访问2(缺失,装入2)→ 访问3(缺失,装入3)→ 访问4(缺失,装入4)
  2. 访问1(命中)→ 访问2(命中)→ 访问5(缺失,淘汰最久未用的3,装入5)
  3. 访问1(命中)→ 访问2(命中)→ 访问3(缺失,淘汰4,装入3)→ 访问4(缺失,淘汰5,装入4)→ 访问5(缺失,淘汰1,装入5)

共12次访问,命中4次,命中率 = 4/12 ≈ 33.3%。若采用FIFO,命中率可能不同,说明替换算法直接影响性能。

关键结论:Cache设计需权衡块大小、相联度、替换算法和写策略。块太大导致强制缺失减少但冲突缺失增加;相联度越高冲突缺失越少但硬件成本越高。

4.3 地址映射方式:主存块如何放入Cache

4.3.1 核心原理:三种映射方式

地址映射决定主存中的每个块可以放置到Cache的哪些位置。三种基本方式:

映射方式主存块可存放位置地址结构优点缺点
直接映射唯一固定位置(Cache行号 = 主存块号 mod Cache行数)标记 + 行号 + 块内地址硬件简单,查找快冲突率高,Cache利用率低
全相联映射任意Cache行标记 + 块内地址冲突率最低,利用率高比较器成本高,查找慢
组相联映射固定组内任意行(组号 = 主存块号 mod 组数)标记 + 组号 + 块内地址折中方案,兼顾速度与命中率硬件复杂度介于两者之间

4.3.2 判断方法:地址字段划分

设主存容量为2^m字节,Cache容量为2^c字节,块大小为2^b字节,则:

  • 块内地址位数 = b
  • Cache行数 = 2^(c-b)
  • 直接映射:主存地址 = 标记(m-c) + 行号(c-b) + 块内地址(b)
  • 组相联映射(每组2^r行):组数 = 2^(c-b-r),主存地址 = 标记(m-c+r) + 组号(c-b-r) + 块内地址(b)
记忆技巧:直接映射的“行号”位数等于Cache行数的对数;组相联的“组号”位数等于组数的对数;标记位数 = 主存地址位数 - 行号/组号位数 - 块内地址位数。

4.3.3 案例拆解:地址划分计算

某计算机主存容量1GB(2^30字节),Cache容量64KB(2^16字节),块大小16B(2^4字节),采用4路组相联映射。计算各字段位数:

  1. 块内地址位数 = 4
  2. Cache行数 = 2^16 / 2^4 = 2^12 = 4096行
  3. 每组4行,组数 = 4096 / 4 = 1024 = 2^10,组号位数 = 10
  4. 标记位数 = 30 - 10 - 4 = 16位

主存地址格式:标记(16位) | 组号(10位) | 块内地址(4位)。CPU访问时,先根据组号定位到Cache中的某一组,再将该组内4个行的标记与主存地址的16位标记逐一比较,若匹配则命中。

4.3.4 常见误区与复盘

误区:直接映射中“行号 = 主存块号 mod Cache行数”意味着多个主存块映射到同一行,但它们的标记不同。判断命中时必须同时比较“行号匹配”和“标记相等”,缺一不可。
易错点:组相联映射中,组号的计算与直接映射的行号计算类似,但组内有多行可供选择,因此冲突率低于直接映射。

4.4 替换算法:Cache满时淘汰谁

4.4.1 核心原理:常见替换算法

  • 随机法(RAND):随机选择一行淘汰,硬件最简单,但未利用局部性,命中率不稳定。
  • 先进先出(FIFO):淘汰最早装入的行,实现简单,但可能淘汰正在频繁使用的“老”数据。
  • LRU(近期最少使用):淘汰最长时间未被访问的行,利用时间局部性,命中率较高,但需要记录访问历史(计数器或栈)。
  • LFU(最不经常使用):淘汰访问次数最少的行,需记录访问频次,可能保留“陈旧热点”数据。

4.4.2 判断方法:LRU的硬件实现

以4路组相联为例,每组内4行分别编号0~3,维护一个2位计数器(或状态位组合):

  1. 每次命中某行,将该行计数器置为最大值(如3),其他行计数器减1(若大于0);
  2. 每次缺失需要替换时,选择计数器值最小的行淘汰;
  3. 新装入的行计数器置为最大值。

这种“计数器法”是LRU的近似实现,实际处理器中常用“伪LRU”树形方法降低硬件开销。

4.4.3 案例拆解:LRU vs FIFO对比

访问序列:A, B, C, D, A, B, E, A, B, C, D, E,Cache容量3块。

步骤访问LRU状态(最左为最久未用)LRU是否命中FIFO状态FIFO是否命中
1AA缺失A缺失
2BA,B缺失A,B缺失
3CA,B,C缺失A,B,C缺失
4DB,C,D(淘汰A)缺失B,C,D(淘汰A)缺失
5AC,D,A(淘汰B)缺失C,D,A(淘汰B)缺失
6BD,A,B(淘汰C)缺失D,A,B(淘汰C)缺失
7EA,B,E(淘汰D)缺失A,B,E(淘汰D)缺失
8AB,E,A(命中A)命中A,B,E(命中A)命中
9BE,A,B(命中B)命中A,B,E(命中B)命中
10CA,B,C(淘汰E)缺失B,E,C(淘汰A)缺失
11DB,C,D(淘汰A)缺失E,C,D(淘汰B)缺失
12EC,D,E(淘汰B)缺失C,D,E(淘汰E? 实际E已在Cache中)命中

LRU命中3次,FIFO命中3次(本例巧合相同),但LRU通常更优。注意FIFO存在“Belady异常”——增加Cache容量反而降低命中率,而LRU不会。

考试重点:LRU是国网考试最常考的替换算法,需掌握其状态更新规则和与FIFO的对比。LRU的硬件实现(计数器法/栈法)也是简答题的高频考点。

4.5 虚拟存储器基础:主存与辅存的统一

4.5.1 核心原理:虚拟存储器的本质

虚拟存储器将主存与辅存统一编址,形成比物理主存大得多的逻辑地址空间。CPU访问的是虚拟地址(逻辑地址),由MMU通过页表/段表转换为物理地址。若页面不在主存中,则触发缺页中断,操作系统从辅存调入所需页面,并可能淘汰一个旧页面。

4.5.2 判断方法:页式虚拟存储器的地址变换

  1. 虚拟地址分为虚页号和页内偏移两部分;
  2. MMU查询TLB(快表)或页表,找到虚页号对应的物理页框号;
  3. 物理地址 = 物理页框号 × 页大小 + 页内偏移;
  4. 若TLB未命中,则访问主存中的页表;若页表项有效位为0,则缺页,转入操作系统处理。
概念说明典型值
页大小虚拟地址与物理地址划分的最小单位4KB / 2MB / 1GB
页表项记录虚页号→物理页框号映射、有效位、访问位、修改位4~8字节/项
TLB页表的Cache,缓存最近使用的页表项64~1024项
缺页率页面不在主存中的访问比例<0.01%

4.5.3 案例拆解:缺页处理流程

某进程访问虚拟地址0x0000_3F2A(页大小4KB,页内偏移0x2A):

  1. 虚页号 = 0x0000_3F2A >> 12 = 0x3F(63号页);
  2. MMU查询TLB,未命中;
  3. 访问主存中的页表,页表项有效位=0,触发缺页中断;
  4. 操作系统检查页表项中的辅存地址,从SSD读取63号页到主存空闲页框(如页框号=0x8A);
  5. 更新页表项(有效位=1,物理页框号=0x8A),刷新TLB;
  6. 重新执行触发缺页的指令,此时TLB命中,完成地址变换。

整个过程对用户透明,但缺页处理代价极高(毫秒级),因此操作系统采用局部性预取和工作集模型减少缺页率。

风险提示:虚拟存储器不是“内存不够用时的临时方案”,而是现代操作系统内存管理的核心机制。它同时实现了内存保护(每个进程独立地址空间)、内存共享(映射同一物理页)和内存扩展(超越物理容量)。

4.5.4 常见误区与复盘

  • 误区1:认为虚拟地址空间大小等于物理内存大小。实际上虚拟地址空间由CPU地址位数决定(如64位可达2^64字节),远大于物理内存。
  • 误区2:混淆Cache缺失与缺页。Cache缺失由硬件处理(几个周期),缺页由操作系统软件处理(几百万个周期),两者不在同一时间量级。
  • 误区3:忽略TLB的作用。TLB缺失不一定是缺页,可能只是页表项不在TLB中,但页表项在主存中有效,只需从主存加载页表项到TLB即可。
本章总结:存储系统的核心是“局部性原理”驱动的层次化缓存。Cache通过地址映射、替换算法和写策略提升CPU访问主存的效率;虚拟存储器通过页表、TLB和缺页中断实现主存与辅存的统一管理。考生应重点掌握:三种映射方式的地址划分、LRU替换过程、页式地址变换流程,以及Cache缺失与缺页中断的区别。