# 第4章 存储器 > 📖 本章介绍存储器的分类、工作原理和层次结构,是课程的重点和难点。 > 🎯 重点理解存储层次、主存组成、Cache和虚拟存储器 --- ## 📋 本章目录 - [[#4.1 概述]] - [[#4.2 主存储器]] - [[#4.3 高速缓冲存储器]] - [[#4.4 虚拟存储器]] - [[#本章小结]] --- ## 4.1 概述 ### 4.1.1 存储器分类 ```mermaid graph TB A[存储器分类] --> B[按存储介质] A --> C[按存取方式] A --> D[按作用] B --> B1[半导体存储器] B --> B2[磁表面存储器] B --> B3[光盘存储器] C --> C1[随机存储器RAM] C --> C2[只读存储器ROM] C --> C3[串行访问存储器] D --> D1[主存储器] D --> D2[辅助存储器] D --> D3[缓冲存储器Cache] ``` #### 按存储介质分类 | 类型 | 特点 | 示例 | |------|------|------| | 半导体存储器 | 体积小、功耗低、速度快、易失性 | SRAM、DRAM | | 磁表面存储器 | 非易失、容量大、速度慢 | 磁盘、磁带 | | 光盘存储器 | 非易失、容量大、可移动 | CD、DVD | #### 按存取方式分类 | 类型 | 特点 | 应用 | |------|------|------| | **RAM** | 随机读写、存取时间与位置无关 | 主存 | | **ROM** | 只读不写(或受限写入) | 固件、BIOS | | **顺序存取** | 按物理顺序寻找(如磁带) | 磁带 | | **直接存取** | 先直接定位区域,再顺序寻找(如磁盘) | 磁盘 | #### RAM和ROM的细分 ```mermaid graph LR RAM[随机存储器RAM] --> SRAM[静态RAM
触发器原理] RAM --> DRAM[动态RAM
电容充放电] ROM[只读存储器ROM] --> MROM[掩模ROM] ROM --> PROM[可编程ROM] ROM --> EPROM[可擦除PROM] ROM --> EEPROM[电擦除PROM] ROM --> Flash[闪速存储器] ``` ### 4.1.2 存储器的层次结构 > [!important] 核心问题 > 速度、容量、价格三者不可兼得,需要通过层次结构解决矛盾。 #### 存储器性能指标关系 ```mermaid graph TB subgraph "存储器层次结构" REG["寄存器
速度最快、容量最小、价格最高"] --> CACHE["Cache
高速缓冲存储器"] CACHE --> MEM["主存储器
主存"] MEM --> DISK["磁盘
辅助存储器"] DISK --> TAPE["磁带
辅助存储器"] end style REG fill:#ff9999 style CACHE fill:#ffcc99 style MEM fill:#ffff99 style DISK fill:#99ff99 style TAPE fill:#9999ff ``` | 层次 | 速度 | 容量 | 价格 | 位置 | |------|------|------|------|------| | 寄存器 | 最快 | 最小 | 最高 | CPU内部 | | Cache | 很快 | 小 | 高 | CPU内部/外部 | | 主存 | 较快 | 中等 | 中等 | 主板 | | 磁盘 | 慢 | 大 | 低 | 外部设备 | | 磁带 | 最慢 | 最大 | 最低 | 外部设备 | #### 两个存储层次 ```mermaid graph TB subgraph "缓存-主存层次" CPU1[CPU] <--> |"速度接近Cache"| CACHE[Cache] CACHE <--> |"容量接近主存"| MEM1[主存] end subgraph "主存-辅存层次" MEM2[主存] <--> |"速度接近主存"| DISK[辅存] CPU2[CPU] -.-> |"不直接访问"| DISK end style CPU1 fill:#ff9999 style CPU2 fill:#ff9999 style CACHE fill:#ffcc99 style MEM1 fill:#ffff99 style MEM2 fill:#ffff99 style DISK fill:#99ff99 ``` **缓存-主存层次**: - 解决CPU和主存**速度不匹配**问题 - 数据调动由**硬件**自动完成 - 对程序员**透明** **主存-辅存层次**: - 解决存储系统**容量**问题 - 数据调动由**硬件+操作系统**完成 - 对程序员**透明** --- ## 4.2 主存储器 ### 4.2.1 主存的基本组成 ```mermaid graph TB subgraph "主存结构" MAR[MAR
地址寄存器] --> |"地址"| DEC[译码器] DEC --> |"选择信号"| MEM[存储体] MEM <--> |"数据"| MDR[MDR
数据寄存器] MDR <--> |"数据"| DBUS[数据总线] MAR <--> |"地址"| ABUS[地址总线] CTRL[控制电路] --> |"读写控制"| MEM end style MAR fill:#ff9999 style MDR fill:#99ccff style MEM fill:#99ff99 style DEC fill:#ffcc99 ``` **工作过程**: 1. **读操作**:CPU将地址送MAR → 地址总线 → 译码器选中单元 → 读出数据到MDR → 数据总线 2. **写操作**:CPU将地址送MAR,数据送MDR → 发写命令 → 数据写入选中单元 ### 4.2.2 主存中存储单元地址的分配 #### 字节寻址与字寻址 ```mermaid graph TB subgraph "IBM 370(32位字长)" A1["地址0"] --> B1["字节0"] A2["地址1"] --> B2["字节1"] A3["地址2"] --> B3["字节2"] A4["地址3"] --> B4["字节3"] A5["地址4(字地址)"] --> B5["下一个字"] end subgraph "PDP-11(16位字长)" C1["地址0(字地址)"] --> D1["字节0"] C2["地址1"] --> D2["字节1"] C3["地址2(字地址)"] --> D3["下一个字"] end ``` > [!note] 地址表示 > - IBM 370:字地址 = 高位字节地址(4的倍数) > - PDP-11:字地址 = 低位字节地址(2的倍数) ### 4.2.3 主存的技术指标 #### 1. 存储容量 $$存储容量 = 存储单元个数 \times 存储字长$$ **字节表示**: $$存储容量 = 存储单元个数 \times 存储字长 / 8$$ > [!example] 示例 > 24位地址线,按字节寻址: > - 寻址范围:$2^{24} = 16M$ 个字节 > - 若字长32位:按字寻址范围 = $16M / 4 = 4M$ 个字 #### 2. 存储速度 | 指标 | 定义 | 关系 | |------|------|------| | **存取时间** | 启动一次操作到完成的时间 | 读出时间或写入时间 | | **存取周期** | 连续两次操作的最小间隔 | 存取周期 > 存取时间 | | **存储器带宽** | 单位时间存取信息量 | 带宽 = 存储字长 / 存取周期 | **提高带宽的措施**: 1. 缩短存取周期 2. 增加存储字长 3. 增加存储体 ### 4.2.4 半导体存储芯片 #### 芯片基本结构 ```mermaid graph LR subgraph "存储芯片" ADDR[地址线] --> DEC[译码驱动] DEC --> MEM[存储矩阵] MEM <--> RW[读/写电路] RW <--> DATA[数据线] CS[片选线] --> DEC RW_CTRL[读写控制线] --> RW end ``` **容量计算**: $$芯片容量 = 2^{地址线位数} \times 数据线位数$$ > [!example] 示例 > - 10根地址线,4根数据线:$2^{10} \times 4 = 4K$ 位 > - 14根地址线,1根数据线:$2^{14} \times 1 = 16K$ 位 #### 译码驱动方式 | 方式 | 特点 | 适用场景 | |------|------|----------| | **线选法** | 一根字线直接选中一个单元 | 容量小的芯片 | | **重合法** | X、Y两个方向译码,交叉点选中 | 大容量芯片 | ```mermaid graph TB subgraph "线选法(16×1字节)" A1["A3A2A1A0 = 1111"] --> B1["第15根字线选中"] B1 --> C1["8位数据读出"] end subgraph "重合法(1K×1位)" A2["地址译码"] --> B2["X方向32根线"] A2 --> C2["Y方向32根线"] B2 --> D2["交叉点选中1位"] C2 --> D2 end ``` ### 4.2.5 随机存取存储器(RAM) #### 静态RAM(SRAM) **基本单元电路**:6个MOS管组成的触发器 **特点**: - 用触发器原理寄存信息 - 速度快,不需要刷新 - 集成度低,功耗大 - 用于Cache **典型芯片**:Intel 2114(1K×4位) #### 动态RAM(DRAM) **基本单元电路**:1个MOS管 + 电容 **特点**: - 用电容充放电原理寄存信息 - 需要定期**刷新** - 集成度高,功耗小 - 用于主存 **典型芯片**:Intel 4116(16K×1位) **刷新方式**: | 方式 | 特点 | 效率 | |------|------|------| | 集中刷新 | 一段时间集中刷新所有行 | 有死区 | | 分散刷新 | 每行刷新分散到各周期 | 无死区,效率低 | | 异步刷新 | 各行刷新均匀分散 | 折中方案 | #### SRAM vs DRAM 对比 | 特性 | SRAM | DRAM | |------|------|------| | 存储原理 | 触发器 | 电容 | | 速度 | 快 | 较慢 | | 集成度 | 低 | 高 | | 功耗 | 大 | 小 | | 刷新 | 不需要 | 需要 | | 价格 | 高 | 低 | | 应用 | Cache | 主存 | ### 4.2.6 只读存储器(ROM) | 类型 | 特点 | 应用 | |------|------|------| | **MROM** | 厂家掩模制作,不可更改 | 批量生产 | | **PROM** | 用户可编程一次 | 小批量 | | **EPROM** | 紫外线擦除,可重复编程 | 开发调试 | | **EEPROM** | 电擦除,可重复编程 | 参数存储 | | **Flash** | 电擦除,速度快 | U盘、SSD | ### 4.2.7 存储器与CPU的连接 #### 存储器容量扩展 **三种扩展方式**: ```mermaid graph TB subgraph "位扩展" A1["芯片1(8位)"] --> C1["组合(16位)"] A2["芯片2(8位)"] --> C1 end subgraph "字扩展" B1["芯片1(1K×8)"] --> D1["组合(2K×8)"] B2["芯片2(1K×8)"] --> D1 end subgraph "字位同时扩展" E1["芯片1"] --> F1["组合"] E2["芯片2"] --> F1 E3["芯片3"] --> F1 E4["芯片4"] --> F1 end ``` | 扩展方式 | 连接方法 | 应用场景 | |----------|----------|----------| | **位扩展** | 地址线、控制线并联,数据线串联 | 增加字长 | | **字扩展** | 地址线、数据线、控制线并联,片选线用高位地址 | 增加字数 | | **字位扩展** | 先位扩展,再字扩展 | 大容量存储器 | #### 存储器与CPU连接示例 ```mermaid graph TB subgraph "CPU" MAR[MAR] --> |"地址"| ADDR[地址总线] MDR[MDR] <--> |"数据"| DATA[数据总线] CTRL[控制信号] --> |"读写"| RW[读写控制] end subgraph "存储器" ADDR --> |"地址"| CHIP1[芯片1] ADDR --> |"地址"| CHIP2[芯片2] CHIP1 <--> |"数据"| DATA CHIP2 <--> |"数据"| DATA CS1[片选1] --> CHIP1 CS2[片选2] --> CHIP2 RW --> CHIP1 RW --> CHIP2 end ``` ### 4.2.8 存储器的校验 #### 奇偶校验 **原理**:增加1位校验位,使数据中1的个数为奇数(奇校验)或偶数(偶校验)。 **特点**: - 简单,只能检测奇数位错误 - 不能纠错 #### 海明码(Hamming Code) **原理**:在数据位中插入多个校验位,通过校验位的组合定位错误位。 **校验位数r满足**:$2^r \geq m + r + 1$(m为数据位数) **特点**: - 可以检测并纠正1位错误 - 可以检测2位错误 > [!example] 示例 > 8位数据需要4位校验码: > - 总位数:8 + 4 = 12位 > - 校验位位置:1, 2, 4, 8 > - 可纠正1位错误 --- ## 4.3 高速缓冲存储器(Cache) ### 4.3.1 Cache的基本原理 > [!important] 为什么需要Cache > CPU速度远快于主存,Cache作为中间缓冲,解决速度不匹配问题。 ```mermaid graph LR CPU[CPU] <--> |"速度匹配"| CACHE[Cache] CACHE <--> |"容量大"| MEM[主存] style CPU fill:#ff9999 style CACHE fill:#ffcc99 style MEM fill:#99ff99 ``` **工作原理**: 1. CPU访问数据时,先查Cache 2. **命中**:直接从Cache读取(快) 3. **未命中**:从主存读取,同时调入Cache ### 4.3.2 Cache命中率 **命中率**: $$H = \frac{N_c}{N_c + N_m}$$ - $N_c$:Cache访问次数 - $N_m$:主存访问次数 **平均访问时间**: $$T_a = HT_c + (1-H)T_m$$ **访问效率**: $$e = \frac{T_c}{T_a} = \frac{1}{H + (1-H)r}$$ 其中 $r = T_m / T_c$(主存与Cache访问时间之比) > [!example] 示例 > Cache命中率95%,Cache访问时间10ns,主存访问时间100ns: > $$T_a = 0.95 \times 10 + 0.05 \times 100 = 14.5ns$$ > $$e = \frac{10}{14.5} = 69\%$$ ### 4.3.3 Cache地址映射 > [!info] 问题 > 主存块如何放入Cache?需要地址映射。 #### 三种映射方式 ##### 1. 直接映射(Direct Mapping) **规则**:每个主存块只能映射到Cache的固定行。 **映射公式**:$i = j \mod m$ - i:Cache行号 - j:主存块号 - m:Cache行数 ```mermaid graph LR subgraph "直接映射" M0[主存块0] --> C0[Cache行0] M1[主存块1] --> C1[Cache行1] Mm[主存块m] --> Cm[Cache行m] Mm1[主存块m+1] --> C0 end ``` **地址结构**: | 标记(Tag) | Cache行号(Index) | 块内地址(Offset) | |-------------|-------------------|-------------------| **优点**:实现简单,查找速度快 **缺点**:灵活性差,命中率低 ##### 2. 全相联映射(Fully Associative Mapping) **规则**:主存块可以映射到Cache的任意行。 ```mermaid graph LR subgraph "全相联映射" M0[主存块0] --> |"任意行"| CACHE[Cache] M1[主存块1] --> |"任意行"| CACHE Mn[主存块n] --> |"任意行"| CACHE end ``` **地址结构**: | 标记(Tag) | 块内地址(Offset) | |-------------|-------------------| **优点**:灵活性好,命中率高 **缺点**:查找速度慢,硬件成本高 ##### 3. 组相联映射(Set Associative Mapping) **规则**:将Cache分组,主存块映射到固定组,组内任意行。 **映射公式**:$q = j \mod u$ - q:Cache组号 - j:主存块号 - u:Cache组数 ```mermaid graph LR subgraph "组相联映射" M0[主存块0] --> G0[Cache组0] M1[主存块1] --> G1[Cache组1] Mu[主存块u] --> Gu[Cache组u] Mu1[主存块u+1] --> G0 end ``` **地址结构**: | 标记(Tag) | 组号(Index) | 块内地址(Offset) | |-------------|--------------|-------------------| **优点**:折中方案,兼顾速度和命中率 **应用**:现代Cache常用2路、4路、8路组相联 #### 三种映射方式对比 | 方式 | 映射规则 | 灵活性 | 命中率 | 硬件复杂度 | |------|----------|--------|--------|------------| | 直接映射 | 固定行 | 差 | 低 | 简单 | | 全相联映射 | 任意行 | 好 | 高 | 复杂 | | 组相联映射 | 固定组,任意行 | 中 | 中 | 中等 | ### 4.3.4 Cache替换算法 > [!info] 问题 > Cache满时,新块调入需要替换旧块,如何选择? #### 常用替换算法 | 算法 | 原则 | 优点 | 缺点 | |------|------|------|------| | **FIFO** | 先进先出 | 实现简单 | 不考虑访问频率 | | **LRU** | 最近最少使用 | 命中率高 | 实现复杂 | | **LFU** | 最不经常使用 | 考虑频率 | 需要计数器 | | **随机替换** | 随机选择 | 实现简单 | 命中率不稳定 | **LRU算法实现**: - 为每行设置计数器 - 每次访问,命中行计数器清零,其他行加1 - 替换计数器值最大的行 ### 4.3.5 Cache写策略 > [!info] 问题 > Cache数据修改后,如何与主存保持一致? #### 写策略 | 策略 | 方法 | 优点 | 缺点 | |------|------|------|------| | **写直达** | 同时写Cache和主存 | 数据一致性好 | 速度慢 | | **写回法** | 只写Cache,替换时写回主存 | 速度快 | 数据可能不一致 | ```mermaid graph TB subgraph "写直达" CPU1[CPU] --> |"写"| CACHE1[Cache] CPU1 --> |"同时写"| MEM1[主存] end subgraph "写回法" CPU2[CPU] --> |"写"| CACHE2[Cache] CACHE2 --> |"替换时写回"| MEM2[主存] end ``` ### 4.3.6 Cache性能分析 **加速比**: $$加速比 = \frac{T_m}{T_a} = \frac{r}{1 + (r-1)H}$$ **Cache容量选择**: - 太小:命中率低 - 太大:成本高,速度可能下降 - 通常:几十KB到几MB --- ## 4.4 虚拟存储器 ### 4.4.1 虚拟存储器的概念 > [!info] 定义 > 虚拟存储器是一个逻辑模型,程序员看到的地址空间远大于实际主存。 **特点**: - **虚拟地址**(逻辑地址):程序员使用的地址 - **物理地址**(实地址):主存实际地址 - 地址转换由硬件和OS自动完成 ```mermaid graph TB subgraph "虚拟存储器" VA[虚拟地址空间
很大] --> |"地址转换"| PA[物理地址空间
较小] PA --> MEM[主存] MEM --> DISK[辅存] end ``` ### 4.4.2 页式虚拟存储器 **基本思想**: - 虚拟地址空间划分为固定大小的**页** - 主存划分为相同大小的**页框** - 通过**页表**建立映射关系 **地址结构**: | 虚页号 | 页内地址 | |--------|----------| **页表项**: | 虚页号 | 实页号 | 有效位 | 修改位 | |--------|--------|--------|--------| **地址转换过程**: 1. 从虚拟地址取出虚页号 2. 查页表得到实页号 3. 实页号 + 页内地址 = 物理地址 ### 4.4.3 TLB(快表) > [!info] 问题 > 页表在主存中,每次访问都要查页表,速度慢。 **解决方案**:在CPU中设置TLB(Translation Lookaside Buffer) **特点**: - 高速小容量存储器 - 存放最近使用的页表项 - 命中率通常 > 99% **访问流程**: 1. 先查TLB 2. **TLB命中**:直接得到物理地址(快) 3. **TLB未命中**:查页表,更新TLB --- ## 📝 本章小结 ### 核心概念 1. **存储层次**:寄存器 → Cache → 主存 → 辅存 2. **主存组成**:存储体 + MAR + MDR + 译码驱动 + 读写电路 3. **RAM分类**:SRAM(快,用于Cache)、DRAM(慢,用于主存) 4. **Cache映射**:直接映射、全相联映射、组相联映射 5. **虚拟存储器**:虚拟地址 → 物理地址的转换 ### 关键公式 - **存储容量** = 存储单元个数 × 存储字长 - **Cache命中率** $H = N_c / (N_c + N_m)$ - **平均访问时间** $T_a = HT_c + (1-H)T_m$ - **访问效率** $e = T_c / T_a$ ### 重点图示 > [!summary] 必须掌握的图 > 1. 存储器层次结构图 > 2. 主存基本组成框图 > 3. Cache三种映射方式示意图 > 4. Cache访问流程图 --- ## 🧪 自测练习 ### 概念题 1. 说明存储器层次结构的必要性。 2. 比较SRAM和DRAM的特点。 3. 解释Cache三种映射方式的区别。 ### 计算题 1. 某系统Cache命中率90%,Cache访问时间20ns,主存访问时间200ns,求平均访问时间和访问效率。 2. 24位地址线,按字节寻址,存储字长32位,求存储容量。 ### 分析题 1. 设计一个16K×8位的存储器,使用4K×4位的芯片。 2. 说明Cache写策略的选择依据。 --- ## 🔗 相关链接 - [[03_系统总线]] - 上一章 - [[05_输入输出系统]] - 下一章 - [[08_CPU结构与功能]] - CPU访问存储器 - [[06_运算方法]] - 数据表示 --- *本章难度:⭐⭐⭐⭐⭐ 困难* *重要程度:⭐⭐⭐⭐⭐ 核心重点*