计算机组成原理 第三章 存储系统
🚥计算机组成原理 系列文章导航🚥
一、存储系统概述
1.存储器的分类
(1)按存储元件分类
存储元件必须有两个截然不同的物理状态才能被用来表示二级制代码 0 和 1。常用的存储有元件有半导体器件、磁性材料和光介质。用这些材料制成的存储器分别称为半导体存储器、磁表面存储器、光盘存储器。
(2)按存取方式分类
-
随机存取存储器(Random Access Memory,RAM):读写任何一个存储单元所需时间都相同,与存储单元所在的物理位置无关。
-
顺序存取存储器(Sequential Access Memory,SAM):读写一个存储单元所需时间取决于存储单元所在的物理位置(如磁带)。
-
直接存取存储器(Direct Access Memory,DAM):既有随机存取特性,也有顺序存取特性。先直接选取信息所在区域,然后按顺序方式存取,存取速度位于 RAM 和 DAM 之间(如磁盘、光盘)。
SAM 和 DAM 读写某个存储单元所需时间都与存储单元的物理位置有关,两者统称为串行访问存储器。
上述的三种存储器都是按所需信息的地址来访问,但有时我们只知道要访问信息的内容特征,此时,只能按内容检索到存储位置进行读写,这种存储器成为按内容访问存储器(Content Addressed Memory,CAM)或相联存储器(Associative Memory)。快表就是一种相联存储器。
注意:相联存储器既可以按地址寻址又可以按内容寻址。
(3)按信息的可更改性分类
-
读写存储器(Read/Write Memory):可读、也可写(如 RAM 芯片)。
-
只读存储器(Read Only Memory):只能读,不能写(用 ROM 表示,BIOS 通常写在 ROM 中)。
注意:RAM 芯片和 ROM 芯片都采用随机存取方式进行信息的访问。ROM 芯片中的信息一旦确定,通常情况下只读不写,但广义上的只读存储器已可通过电擦除等方式进行写入,“只读” 的概念没有保留,但仍保留了断电内容保留、随机读取特性,但其写入速度比读取速度慢得多。
(4)按断电后信息的可保存性分类
-
易失性存储器(Volatile Memory):电源关闭时信息自动丢失(如 RAM、Cache)。
-
非易失性存储器(Nonvolatile Memory):信息可一直保留,不需电源维持(如 ROM、磁表面存储器、光存储器)。
(5)按功能分类
-
高速缓冲存储器:简称 Cache,位于主存和 CPU 之间,用来存放当前 CPU 经常使用的指令和数据。
-
主存储器:简称主存,也称内存储器(内存),用来存放计算机运行期间所需的程序和数据,CPU 可以直接随机地对其进行访问。主存也可和 Cache 及辅助存储器交换数据。
-
辅助存储器:简称辅存,也称外存储器(外存),用来存放当前暂时不用的程序和数据,以及一些需要永久保存的信息。辅存的内容需要调入主存后才能被 CPU 访问。
注意:也有些地方将辅存与外存区分开,辅存指磁盘存储器,外存指辅存和容量更大,速度更慢的磁带存储器和光盘存储器。
2.存储器的性能指标
(1)存储容量 = 存储字数 × 字长(如 1M × 8 位)
存储字数表示存储器的地址空间大小,字长表示一次存取操作的数据量。
(2)单位成本:价位 = 总成本/总容量
(3)存储速度:数据传输速率(每秒传送信息的位数)= 数据的宽度/存取周期
-
存取时间(T_a):指从启动一次存储器操作到完成该操作所经历的时间,分为读出时间和写入时间。
-
存取周期(T_m):存取周期是指存储器进行一次完整的读/写操作所需要的全部时间,即连续两次独立访问存储器操作之间所需的最小时间间隔。
-
主存带宽(B_m):也称数据传输速率,表示每秒从主存进出信息的最大数量,单位为字/秒、字节/秒(B/s)或位/秒(b/s)。
存取周期大于存储时间,因为任何一种存储器在进行读写操作后都需要一段恢复内部状态的复原时间。

3.存储器的层次结构
存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。
Cache-主存层主要解决 CPU 和主存速度不匹配的问题,主存和 Cache 之间的数据调动是由硬件自动完成的,对所有程序员均是透明的。
主存-辅存层主要解决存储系统的容量问题,主存和辅存之间的数据调动是由硬件和操作系统共同完成的,对应用程序员是透明的(此处的透明均为看不见的意思)。
二、主存储器
1.主存储器的基本组成
下图为一个单管动态 MOS 管存储元件,MOS 管用于控制电路的通断,电容存在有电和没电两种状态,可用于表示 0 和 1 两种二进制代码。
像这样一个个存储 0 或 1 的记忆单元(也称存储元件、存储单元)构成的存储矩阵(也称存储体、存储阵列),是存储器的核心部件。
图中一行存储元件构成一个存储单元,地址线每次控制访存一整个存储单元的内容。也就是说,每次同时访存一整个字。而片选线用于选择要交互的芯片。
封装后的主存如下图所示:
当需要访问主存时,CPU 首先把被访问单元的地址送到 MAR 中,然后通过地址线将主存地址送到主存中的地址寄存器,以便地址译码器进行译码,选中相应单元,同时 CPU 将读/写控制信号通过读/写控制线送到主存的读写控制电路。根据选择的不同,通过数据线将数据从存储体送进 MDR(读)或从 MDR 送进存储体(写)。
MAR 的位数与地址线的位数相同,MDR 的位数与数据线的位数相同。
以 64K × 32 位的芯片为例,我们可以计算出地址线和数据线的位数分别为 16 和 32(这里默认按字寻址,根据寻址方式的不同,地址线的个数也会不一样,例如如果按字节寻址,则地址线的个数应为 18,可表示的地址范围要扩大四倍)。
注意:数据线的位数通常等于存储字长,因此 MDR 的位数通常等于存储字长;若数据线的位数不等于存储字长,则 MDR 的位数由数据线的位数决定。
2.SRAM 和 DRAM
(1)存储元特性差异
半导体分为随机存储器(RAM)和只读存储器(ROM)。RAM 又分为动态随机存储器(Dynamic Random Access Memory,DRAM)和静态随机存储器(Static Random Access Memory,SRAM)。
上面我们刚刚讲到的单 MOS 管存储元使用栅极电容来存储信息,除此之外还可以用由 6 个 MOS 管组成的双稳态触发器来存储信息,它有 A 高 B 低和 A 低 B 高两种稳定的状态来表示二进制代码。

DRAM 芯片:采用栅极电容存储信息,成本低,功耗低,集成度高,但由于是破坏性读出,读出后需要有重写操作,因此存取速度慢。
SRAM 芯片:采用双稳态触发器存储信息,成本高,功耗高,集成度低,为非破坏性读出,读出后不需要重写,因此存取速度快。
主存储器主要都是由 DRAM 实现,而靠近处理器的那一层(Cache)则由 SRAM 实现。
(2)DRAM 的刷新
栅极电容上的电荷一般只能维持 1 到 2 ms,即使电源不断电,信息也会自动消失,因此需要定时刷新。而双稳态触发器只要持续供电,存储的信息就不会消失。
对于 DRAM 芯片的刷新采用读出的方式进行,根据读出内容对相应单元进行重写,即读后再生,对同一行进行相邻两次刷新的时间间隔称为刷新周期,通常取 2ms。
DMA 的刷新单位是行。那么,什么是行呢?
为了减少与地址译码器相连的选通线的数量,一般将存储单元的地址拆分为二维的行列地址。对于以 8 位地址为例,如果采用一维地址,则需要有 2^8 = 256 根选通线与译码器相连,而如果采用二维地址,则只需要 2^4 + 2^4 = 32 根选通线。

注意:DRAM 芯片容量较大,地址位数较多,为了减少芯片的地址引脚数,通常采用地址引脚复用技术,行地址和列地址通过相同的引脚分先后两次输入,这样地址引脚数可减少一半(SRAM 则不采用这种复用技术,而是同时送入行列地址)。
注意:对于一个 2^n × b 位 DRAM 芯片的存储阵列,其行数为 r,列数为 c,则 2^n = r × c。由于 DRAM 采用地址引脚复用技术,为减少地址引脚数,应尽量使行、列位数相同。又因为 DRAM 按行刷新,为减少刷新开销,应使行数较小,即当行列无法相同时,行数应为较小的哪个数。
常用的刷新方式有以下三种:
集中刷新:在整个刷新间隔内,前一段时间用于正常的读写操作,后一段时间停止读写操作,集中逐行进行刷新。在此期间停止对存储器的读/写操作,称为死时间,也称访存死区。
优点是读/写操作期间不受刷新操作的影响;缺点是集中刷新期间不能访问存储器。
分散刷新:将存储器系统的工作周期分为两部分,前半部分用于正常的读写操作,后半部分用于刷新。这种方式增加了系统的存取周期,如存储芯片的存取周期为 0.5us,刷新所需时间为 0.5us,则系统的存取周期为 1us。
优点是没有死区;缺点是加长了系统的存取时间。
注意:分散刷新的刷新操作是独立于读写操作的,不是只刷新被读写的行,而是按照固定顺序依次刷新,并且无论是否有读写请求,控制器都会在每个周期的后半段执行刷新,确保在 2ms 内覆盖全部存储单元。
异步刷新:结合前两种方式,2ms 内每行刷新一次即可。如存取周期为 0.5us,排列成 128 × 128 的存储芯片,可采取在 2ms 内对 128 行各刷新一遍,即每隔 2000us ÷ 128 = 15.6us 刷新一行。若每行刷新的时间为 0.5us,则对每行来说,刷新时间仍为 2ms,但死时间缩短为 0.5us。
通过这种方式使死时间的分布更加分散,避免让 CPU 连续等待过长的时间。
(3)DRAM 芯片的行缓冲器
DRAM 芯片内部有一个行缓冲器,用来缓存指定行中每列的数据,其大小为 列数 × 存储元的位数,常用 SRAM 实现。
选中某行后,该行的所有数据都被送到行缓冲器,以后每个时钟都可以连续地从 DRAM 中输出一个数据,因此可支持突发传输(突发传输方式是指在寻址阶段给出数据的首地址,在传输阶段可传送多个连续存储单元的数据)。
(4)SRAM 和 DRAM 的比较
特点 | SRAM | DRAM |
---|---|---|
存储信息 | 双稳态触发器 | 栅极电容 |
破坏性读出 | 非 | 是 |
需要刷新 | 不要 | 要 |
送行列地址 | 同时送 | 分两次送(复用) |
运行速度 | 快 | 慢 |
集成度 | 低 | 高 |
存储成本 | 高 | 低 |
主要用途 | 高速缓存 | 主机内存 |
SDRAM芯片技术
目前主存常用的是基于 SDRAM(Synchronous DRAM,同步动态随机存储器) 芯片技术的内存条。与传统的异步 DRAM 不同,SDRAM 与 CPU 的数据交换同步于系统的时钟信号,并且以 CPU-主存总线的最高速度运行,而不需要插入等待状态。
在传统 DRAM 中,CPU 将地址和控制信号送至存储器后,需经过一段延迟时间,数据才读出或写入。在此期间,CPU不断采样 DRAM 的完成信号,在读写完成之前,CPU 不能做其他工作,降低了 CPU 的执行速度。而 SDRAM 在系统时钟的控制下进行数据的读出和写入,它将 CPU 发出的地址和控制信号封锁起来,经过指定的时钟周期数后再响应,此时 CPU 可执行其他操作。
3.只读存储器 ROM
ROM 芯片具有两个显著的优点:结构简单,所以位密度比可读/写存储器的高;具有非易失性,所以可靠性高。
根据制造工艺的不同,ROM 可分为以下几种:
(1)MROM(Mask Read-Only Memory)—— 掩模式只读存储器
厂家按照客户需求,在芯片生产过程中直接写入信息,之后任何人不可重写。可靠性高、灵活性差、生产周期长、只适合批量定制。
(2)PROM(Programmable Read-Only Memory)—— 可编程只读存储器
用户可用于专门的 PROM 写入器写入信息,写一次之后就不可更改。
(3)EPROM(Erasable Programmable Read-Only Memory )—— 可擦除可编程只读存储器
允许用户写入信息,之后通过某种方式擦除数据,可进行多次重写。
-
UVEPROM(Ultra Violet EPROM):用紫外线照射一段时间,擦除所有信息。
-
EEPROM(Electrically EPROM):可用 “电擦除” 的方式,擦除特定的字。
注意:虽然 EPROM 可读可写,但它不能取代 RAM,因为 EPROM 的编程次数有限,且写入时间过长。
(4)Flash Memory —— 闪速存储器
Flash 存储器是在 EPROM 的基础上发展起来的,它兼有 ROM 和 RAM 的特优点,可在不加电的情况下长期保存信息,又能在线进行快速擦除重写。
Flash 存储器既有 EPROM 价格便宜、集成度高的优点,又有 EEPROM 电可擦除重写的特点,且擦除重写的速度快。
U 盘、SD 卡就是 Flash 存储器,由于其需要先擦除再写入,因此 Flash 存储器的写速度要比读速度慢。
Flash 存储器的每个存储元只需单个 MOS 管(无需电容),位密度比 RAM 更高。
(5)SSD(Solid State Drive)—— 固态硬盘
基于闪存的固态硬盘由控制单元和存储单元(Flash 芯片) 组成。保留了 Flash 存储器长期保存信息、快速擦除与重写的特点,对比传统硬盘也有读/写速度快、低功耗的特点,缺点是价格较高。
计算机内的重要 ROM
主板上的 BIOS 芯片(ROM)存储了 “自举装入程序”,负责引导装入操作系统(开机)。虽然 BIOS 芯片位于主板上,但从逻辑上讲,主存是由 RAM + ROM 构成的,且二者常常统一编址。因此主板上的 ROM 芯片也是主存的一部分。
注意:ROM 芯片虽然名字是只读,但很多 ROM 也是可写的;RAM 芯片虽然叫随机存储器,但 ROM 同样也具有随机存取的特性,即访问的速度不会因地址的不同而变化。
4.多模块存储器
CPU 的速度比存储器快得多,且在连续读写存储器时,必须等待一段恢复时间才能进行下一次读写,无法充分利用 CPU 资源。而多模块存储器是一种空间并行技术,利用多个结构完全相同的存储模块的并行工作来提高存储器的吞吐率。
常用的有单体多字存储器和多体低位交叉存储器。
(1)单体多字存储器
单体多字系统中,每个存储单元存储 m 个字,总线宽度也为 m 个字,一次并行读出 m 个字。在一个存取周期内,从同一地址读出 m 个字。相当于每隔 1/m 个存取周期,CPU 向主存读取一个字,提高了单体存储器的工作速度。
缺点:每次只能同时读取 m 个字,不能单独读取其中某个字。当要读取的数字不是连续存放时,提升效果不明显。
(2)多体并行存储器
多体并行存储器由多体模块组成。每个模块都有相同的容量和存取速度,各模块都有独立的读/写控制电路、地址寄存器和数据寄存器。
多体并行存储器分为高位交叉编址和低位交叉编址两种:
高位交叉编址用高位来区分不同的模块,低位交叉编址用低位来区分不同的模块。
每个存储体的存取周期为 T,存取时间为 r,假设 T = 4r。当 CPU 读取连续的几个字时,两种交叉编址方式下的读取时间如下图所示:
可以看到,高位交叉编址本质上只是相当于单纯的扩容,并不能实现并行工作,因此这种存储器仍是顺序存储器。而低位交叉编址情况下,多个存储体可以以流水线的形式被并行访问,充分利用了 CPU 资源。
低位交叉方式中,程序连续存放在相邻的模块中,因此称采用此编址方式的存储器为交叉存储器。
交叉存储器可以采用轮流启动或同时启动两种方式。
为了实现轮流启动方式,存储器交叉模块数应大于或等于 m = T/r,按照每隔 1/m 个存取周期轮流启动各模块,则每隔 1/m 个存取周期就可读出或写入一个数据,存取周期提高了 m 倍。
连续读取 m 个字所需的时间为 t = T + (m - 1)r(哎,真的要这么算吗)。
注意:若相邻的 m 次访问的访存地址出现在同意模块内,则会发生访存冲突,此时需延迟发生冲突的访问请求。
同时启动方式:同时启动所有模块进行读写。如果所有存储模块一次并行读写的总位数正好等于系统总线中的数据线数,则可采用同时启动方式。设每个模块一次读/写的位数为 16 位,模块数 m = 4,数据总线位数为 64,4 个模块一共提供 64 位,正好构成一个存储字,因此同时启动 4 个模块并行读/写。
三、主存储器与 CPU 的连接
1.连接原理

-
主存储器通过数据总线、地址总线和控制总线与 CPU 连接。
-
数据总线的位数与工作频率的乘积正比于数据传输速率。
-
地址总线的位数决定了可寻址的最大空间内存。
-
控制总线(读/写)指出总线周期的类型和本次输入/输出操作完成时间。
单个芯片的容量有限,因此通过存储器芯片扩展技术,将多个芯片集成在一个内存条上,然后由多个内存条及主板上的 ROM 芯片组成计算机所需的主存空间,再通过总线与 CPU 相连。
2.主存容量的扩展
(1)位扩展
位扩展是对字长进行扩展(增加存储字长),当 CPU 的系统数据线数多于存储芯片的数据位数时,必须对存储芯片扩位,使其数据位与 CPU 的数据线数相等。

(2)字扩展
字扩展是指对存储字的数量进行扩展,而存储字的位数满足要求。系统数据线位数等于芯片数据线位数,系统地址线位数多于芯片地址线位数(多出来的用于片选)。
片选信号的产生有两种方法:
线选法:
线选法用除片内寻址外的高位地址线直接连接至各个存储芯片的片选端,这些片选地址线每次选址时只能有一位有效位,不允许有多位同时生效,这样才能保证每次直选中一个芯片(或芯片组)。
优点是不需要译码器,线路简单。缺点是地址空间不连续,地址空间不连续,不能充分利用系统的存储器空间,造成地址资源的浪费。

译码片选法:
译码片选法用除片内寻址外的高位地址线通过地址译码器产生片选信号。

(3)字位扩展

3.存储器与 CPU 的连接
-
选择合适存储芯片:选用 ROM 存放系统程序、标准子程序和各类常数,RAM 则是为用户编程而设置的。
-
地址线的连接:CPU 地址线的低位与存储芯片的地址线相连,高位用于在字扩展时进行片选。
-
数据线的连接:CPU 的数据线与存储芯片的数据线数不等时需进行位扩展。
-
读写控制线的连接
-
片选控制线的连接
四、外部存储器
1.磁盘存储器
(1)特性
磁盘存储器是以磁盘为介质的存储器,有以下优点:
-
存储容量大,价位低。
-
记录介质可重复使用。
-
记录信息可长期保存而不丢失,甚至可以脱机存档。
-
非破坏性读出,读出时不需要再生。
缺点是存取速度慢,机械结构复杂,对工作环境要求高。
(2)磁盘设备的组成
1.磁盘存储器的组成:磁盘存储器由磁盘启动器、磁盘控制器和盘片组成。
-
磁盘驱动器:驱动磁盘转动并在盘面上通过磁头进行读/写操作的装置。
-
磁盘控制器:磁盘驱动器与主机的接口,负责接收并解释 CPU 发来的命令,向磁盘驱动器发出各种控制信号,并负责检测磁盘驱动器的状态。
2.存储区域:一个磁盘含有若干记录面,每个记录面划分为若干圆形的磁道,而每条磁道又划分为若干扇区,扇区(也称块)是磁盘读/写的最小单元,即磁盘按块存取。
-
磁头数(Heads):即记录面数,表示磁盘共有多少个磁头,磁头用于读取盘上记录面的信息和写入信息,一个记录面对应一个磁头(顶部和底部两面没有磁头,也没有存储信息)。
-
柱面数(Cylinders):表示磁盘每面盘片上有多少条磁道。在一个盘组中,不同记录面的相同编号(位置)的诸磁道构成一个圆柱面。
-
扇区数(Sectors):表示每条磁道上有多少个扇区。
3.磁盘高速缓存(Disk Cache):在内存中开辟一部分区域,用于缓冲将被送到磁盘上的数据。优点:写磁盘时是按 “簇” 进行的,可以避免频繁地用小块数据写盘(将碎片化的小数据合并为批量操作,减少物理写入次数);有些中间结果在写回磁盘之前可被快速地再次使用(避免不必要的磁盘往返,加速数据处理流程)。

(3)磁盘的性能指标
1.磁盘的容量:一个磁盘所能存储的字节总数称为磁盘容量。磁盘容量有非格式化容量和格式化容量之分。
-
非格式化容量:磁记录表面可以利用的磁化单元总数。
-
非格式化容量 = 记录面数 × 柱面数 × 每条磁道的磁化单元数
-
格式化容量:指按某种特定的记录格式所能存储信息的总量,即用户可以使用的容量,一般为非格式化容量的 60% 到 70%。
-
格式化容量 = 记录面数 × 柱面数 × 每道扇区数 × 每个扇区的容量
2.记录密度:指盘片单位面积上记录的二进制的信息量,通常以道密度、位密度、面密度表示。
-
道密度:沿磁盘半径方向单位长度上的磁道数。
-
位密度:磁道单位长度上能记录的二进制代码位数。
-
面密度:位密度和道密度的乘积。
注意:磁盘所以磁道记录的信息量一定是相等的,并不是圆越大信息越多,故每个磁道的位密度都不同。
3.存取时间:平均存取时间 = 寻道时间 + 旋转延迟时间 + 传输时间
-
寻道时间:磁头移动到目的磁道(一般取平均值,即从最外道移动到最内道时间的一半)
-
旋转延迟时间:磁头定位到所在扇区(一般取平均值,即旋转半周的时间)
-
传输时间:传输数据所花费的时间
4.数据传输速率:磁盘存储器在单位时间内向主机传送数据的字节数,称为数据传输率。
-
假设磁盘转数为 r 转/秒,每条磁道容量为 N 字节,则数据传输率为 D_r = rN。
(4)磁盘地址
磁盘的地址划分为柱面(磁道)号、盘面号、扇区号,有时前面还会有驱动器号:
(5)磁盘工作过程
硬盘的主要操作是寻址、读盘、写盘。每个操作都对应一个控制字,硬盘工作时,第一步是取控制字,第二步是执行控制字。
硬盘属于机械式部件,其读写操作是串行的,不可能在同一时刻既读又写,也不可能在同一时刻读两组数据或写两组数据。
2.磁盘阵列
RAID(独立冗余磁盘阵列) 是指将多个独立的物理磁盘组成一个独立的逻辑盘,数据在多个物理盘上分割交叉存储、并行访问,具有更好的存储性能、可靠性和安全性。
RAID 分级如下,在 RAID1 到 RAID5 的几种方案中,无论何时有磁盘损坏,都可以随时拔出受损的磁盘再插入好的磁盘,而数据不会损坏,提升了系统的可靠性。
-
RAID0:无冗余和无校验的磁盘阵列
-
RAID1:镜像磁盘阵列
-
RAID2:采用纠错的海明码的磁盘阵列
-
RAID3:位交叉奇偶校验的磁盘阵列
-
RAID4:块交叉奇偶校验的磁盘阵列
-
RAID5:无独立校验的奇偶校验磁盘阵列
3.固态硬盘
(1)特性
固态硬盘(SSD) 是一种基于闪存技术的存储器,属于电可擦除 ROM,即 EEPROM。
一个 SSD 由一个或多个闪存芯片和闪存翻译层组成。闪存芯片替代传统旋转磁盘中的机械驱动器,而闪存翻译层将来自 CPU 的逻辑块读/写请求翻译成对底层物理设备的读/写控制信号。

SSD 以页为单位进行读写,页相当于磁盘的一个扇区;以块为单位进行擦除,每次擦除一整块。
对于一个写满的块,如果想只擦除其中一页进行重新,保留其他页,可以其将复制到另一个块内,同时写入想要修改的新数据,然后把原来的块擦除。数据进行迁移后,闪存翻译层会重新映射该块逻辑地址所对应的物理地址。
与机械硬盘相比,SSD 有如下特点:
-
读写速度快,随机访问性能高,用电路控制访问位置(支持随机访问);机械硬盘通过移动磁臂旋转磁盘控制访问位置,有寻道时间和旋转延迟(不支持随机访问)。
-
安静无噪音、耐摔抗震、能耗低、造价更贵。
-
SSD 的一个块被擦除次数过多(重复写同一个块)可能会损坏,而机器硬盘的扇区不会因为写的次数太多而坏掉。
(2)磨损均衡技术
闪存的擦写寿命是有限的,因为需要将擦除平均分布在各个块上,以提升使用寿命,为此引入了磨损均衡技术。
SDD 的磨损均衡技术大致分为两种:
-
动态磨损均衡:写入数据时,优先选择擦除次数更少的新闪存块。
-
静态磨损均衡:这种技术更为先进(什么,静态更先进,真的假的),就算没有数据写入,SSD 也会监测并自动进行数据分配,让老的闪存快承担以读为主的存储任务。同时让较新的闪存快腾出空间,以承担更多以写为主的存储任务。
五、高速缓冲存储器
1.程序访问的局部性原理
程序访问的局部性原理包括时间局部性和空间局部性。
-
时间局部性:指最近的未来要用到的信息,很可能是现在正在使用的信息,因为程序中存在循环和需要多次重复执行的子程序段,已经对数组的存储和访问。
-
空间局部性:指最近的未来要用到的信息,很可能与现在正在使用的信息在存储空间上是临近的,因为指令通常是顺序存放、顺序执行的,数据一般也是以向量、数组等形式簇聚地存储的。
以上图两个程序为例:
对于数组 a ,程序 A 按行访问数组,访问顺序与存放顺序一致,因此空间局部性好;两个程序中,数组 a 每个元素都只被访问一次,因此两者数组 a 的时间局部性都差。
对于for循环体,两个程序的访问局部性是一样的。因为循环体内指令按序连续存放,所以空间局部性好;内循环体被连续执行多次,因此时间局部性也好。
2.Cache 的基本工作原理
高速缓冲技术利用局部性原理,把程序中正在使用的部分数据存放在一个高速的、容量较小的 Cache 中,使 CPU 的访存操作大多数针对 Cache 进行,从而提高程序的执行速度。
Cache 被集成在 CPU 内部,由 SRAM 组成,速度快、成本高、集成度低。
为便于 Cache 与主存交换信息,Cache 和主存都被划分为大小相等的块,Cache 块也称 Cache 行,每块由若干字节组成,块的长度成为块长(也称行长)。Cache 中的块数远小于主存,仅保存主存中最活跃的若干块的副本。
当 CPU 发出读请求时,若访存地址在 Cache 中命中(也称 Cache 命中),就将此地址转换成 Cache 地址,直接对 Cache 操作,与主存无关;若未命中,则仍需访问主存,并将此字所在的字块一次性从主存调入 Cache。若 Cache 已满,则需要借助某种替换算法。
注意:CPU 与 Cache 之间的数据交换以字为单位,而 Cache 与主存之间的数据交换则以 Cache 块为单位。
当 CPU 发出写请求时,若命中,有可能遇到 Cache 与主存中的内容不一致的问题(即只修改了 Cache 的内容,主存的内容没有改)。此时需要一定的写策略处理。
注意:有些计算机是同时访问 Cache 和主存,如果在 Cache 中找到则停止对主存的访问。在计算 Cache 命中对访问时间影响相关问题时,要注意计算机采用的是哪种访问方式。
3.Cache 和主存的映射方式
Cache 行数比主存块数小得多,能存存放主存一部分块的信息,因此在 Cache 中要为每块加一个标记位,指明它是主存中哪一块的副本。此外还需要一位有效位(0/1) 来说明 Cache 行中的信息是否有效。
即 Cache 中存储的信息为:有效位(0/1)+ 标记位 + 整块数据
注意:实际上完整的 Cache 标记项包括:有效位、一致性维护位(脏位)、替换算法位、标记位。
主存地址空间与 Cache 地址空间的映射方式有以下三种:
-
直接映射:每个主存块映射到 Cache 的固定行中。
-
全相联映射:每个主存块映射到 Cache 的任意行中。
-
组相联映射:每个主存块映射到 Cache 的固定组的任意行中。
我们假设计算机的主存地址空间大小为 256 MB(2^22 块),按字节编址,其数据 Cache 有 8 个 Cache 行,行长为 64 B。
(1)直接映射
主存中的每一块只能装入 Cache 中的唯一位置,若这个位置已有内容,则产生块冲突,原来的块将无条件地被替换出去(无需替换算法)。
直接映射的关系可定义为:
可以看到,Cache 行号与主存块号的末尾三位相同(取余得到),因此在存储时,我们只需要 22 - 3 = 19 个标记位。
CPU 访问主存地址 0…01000 001110 时,根据主存块号的后三位确定 Cache 行,如果主存块号的前 19 位与 Cache 标记匹配且有效位为 1,则 Cache 命中。
优点:实现简单,命中时间短。
缺点:不够灵活,使得 Cache 存储空间得不到充分利用,空间利用率最低;命中率较低。
(2)全相联映射
主存的每一块可以装入 Cache 中的任何位置,因此 CPU 访存时需要与所有 Cache 行的标记进行比较。
CPU 访问主存地址 1…1101 001110 时,先对比 Cache 中所有块的标记,若标记匹配且有效位为 1,则 Cache 命中,访问块内地址为 001110 的单元。
优点:Cache 块的冲突概率低,只要有空闲 Cache 行,就不会发生冲突;空间利用率高;命中率高。
缺点:标记的比较速度较慢;实现成本较高,通常需要采用按内容寻址的相联存储器。
(3)组相联映射
将 Cache 分成 Q 个大小相等的组,每个主存块可以装入固定行中的任意一行,即组间采用直接映射,组内采用全相联映射的方式。下图中每组有两个 Cache 行,分为四组,称为 2 路组相联。
组相联映射的关系可定义为:
与直接映射同理,Cache 标记只需要存储主存地址块号的前 22 - 2 = 20 位
当 CPU 访问主存地址 1…1101 001110 时,先根据主存块号的后两位确定所属分组号,若主存块号的前 20 位与分组内的某个标记匹配且有效位为 1,则 Cache 命中,访问块内地址为 001110 的单元。
组相联映射是对直接映射和全相联映射的一种折中。
比较器
在访存时,比较器根据标记字段的内容来访问 Cache 行中的主存块,因此其查找过程是一种按内容访问的存取方式,所以是一种相联存储器(CAM)。比较器的位数等于标记字段的位数。直接映射因为每块只能映射到唯一的 Cache 行,因此只需要设置 1个比较器;全相联映射需要为每个 Cache 行都设置一个比较器;r 路组相联映射需要在对应分组中与 r 个 Cache 行进行比较,因此需设置 r 个比较器。
4.Cache 中主存块的替换算法
采用全相联映射或组相联映射方式时,若 Cache 或 Cache 组中的空间已经被占满时,就需要使用替换算法置换 Cache 行(直接映射不需要,因为它只有唯一的固定位置)。
常用的替换随机算法有以下几种:
(1)随机(RAND)算法:随机地确定替换的 Cache 行。实现简单,但未依据程序访问的局部性原理,因此可能命中率较低。
(2)先进先出(FIFO)算法:选择最早调入的 Cache 行进行替换。比较容易实现,但也未依据程序访问的局部性原理,因为早进入的主存储块也可能是目前经常要用的,可能会出现抖动现象。
抖动现象:频繁的换入换出现象,即刚被替换的块很快有被调入。
(3)近期最少使用(LRU)算法:依据程序访问的局部性原理,选择近期内长久未访问过的 Cache 行进行替换,其平均命中率要比 FIFO 高,是堆栈类算法。
LRU 算法对每个 Cache 行设置一个计数器(也称 LRU 替换位),用计数值来记录主存块的使用情况,根据计数值来选择淘汰某个块。计数值的大小与 Cache 组大小有关,若为 2^n,块,则计数器只需 n 位(向上取整)。
计数器的变化规则为:
-
命中时,所命中行的计数器清零,比其低的计数器加 1, 其余不变(比其高的计数器加 1 无意义,对排序没有影响,且会造成计数器的溢出)。
-
未命中且还有空闲行时,新装入的行的计数器置 0,其余非空闲行全加一。
-
未命中且无空闲行时,计数值为 2^n - 1 的信息块被替换,新装入的行的计数器置 0,其余全价 1。
注意:当集中访问的存储区超过 Cache 组的大小时,命中率可能会变得很低,即出现抖动现象。此外虽然叫计数器,但原理更像是排队,当 Cache 存满时,计数器值为 0 到 2^n -1 的 Cache 行均存在且只有一个。
(4)最不经常使用(LFU)算法:将一段时间内被访问次数最少的 Cache 行换出。每行也需设置一个计数器,新行装入后从 0 开始计数,每访问一次,被访问的行计数器加 1,需要替换时比较各特定行的值,将计数值最小的行换出。若有多个计数器最小的行,可按行号递增或 FIFO 等策略进行选择。
缺点:计数器的值可能会很大;曾经被经常访问的主存块在未来不一定会用到,没有很好地遵循局部性原理,实际效果不如 LRU。
5.Cache 的一致性问题
Cache 中的内容是主存块副本,当对 Cache 中的内容进行更新时,就需要选用写操作策略使 Cache 内容和主存内容保持一致。
(1)写策略
1.写命中时,有全写法(直写法、Write Through)和回写法(Write Back)两种策略。
全写法:当 CPU 对 Cache 写命中时,必须把数据同时写入 Cache 和主存。
为了减少全写法直接写入主存的时间损耗,在 Cache 和主存之间加一个写缓冲(Write Buffer),写缓冲是用 SRAM 实现的FIFO队列,CPU与写缓冲交互的速度远大于与主存交互的速度。写缓存可以解决速度不匹配的问题,但若出现频繁写时,会使写缓冲饱和溢出。
回写法:当 CPU 对 Cache 写命中时,只把数据写入 Cache,而不立即写入主存,只有当此块被替换出时才写回主存。
这种方法减少了访存次数,但存在数据不一致的隐患。此外需要给每个 Cache 行设置一个修改位(脏位),若脏位为 1,则说明对应 Cache 行中的块被修改过,替换时需写回主存;若脏位为 0,则说明未被修改过,不必回写。
2.写不命中时,有写分配法(Write Allocate)和非写分配法(Not Write Allocate)两种策略。
写分配法:更新主存单元,然后把这个主存块调入 Cache 中。
试图利用程序的空间局部性,缺点是每次写不命中都要从主存读一个块到 Cache 中。
非写分配法:只更新主存单元,而不把主存块调入 Cache。
注意:写分配法通常和回写法合用,用于 Cache 和主存之间;非写分配法通常与全写法合用,用于 各层 Cache 之间。
(2)指令和数据 Cache
随着指令流水技术的发展,需要将指令 Cache 和数据 Cache 分开设计,这就有了分离的 Cache 结构。
统一 Cache 的优点是设计和实现相对简单,但由于执行部件存取数据时,指令预取部件要从同一 Cache 读指令,会引发冲突。采用分离的 Cache 可以解决这个问题,且分离的指令和数据 Cache 还可以充分利用指令和数据的不同局部性来优化性能。
(3)多级 Cache 结构
现代计算机的 Cache 通常设立多级 Cache,假定 2 级 Cache,按离 CPU 的远近可各自命名为 L1 Cache、L2 Cache,离 CPU 越远,访问速度越慢,容量越大。
指令 Cache 与数据 Cache 分离一般在 L1 级,此时通常为写分配法与回写法合用。下图为含有两级 Cache 的系统,L1 Cache 对 L2 Cache 使用全写法,L2 Cache 对主存使用回写法,由于 L2 Cache 的存在,其访问速度大于主存,所以避免了因频繁写时造成的写缓冲饱和溢出。
六、虚拟存储器
1.页式存储器
页式存储系统:一个程序在逻辑上被分为若干个大小相等的 “页面”,“页面” 大小与 “块” 的大小相同。每个页面可以被离散地放入不同的主存块中。
-
逻辑地址(虚地址):程序员视角看到的地址(逻辑页号 + 页内地址)
-
物理地址(实地址):实际在主存中的地址(主存块号 + 块内地址)
计算机拿到一个逻辑地址,可根据先根据地址上的逻辑页号和其与主存块号的映射关系查找到信息存放的位置,然后根据页内地址在对应的块内查询相应的块内地址(页内地址与块内地址相同)。
逻辑页号和主存块号的映射关系则存储在页表中,CPU 可以通过查询页表将逻辑地址转换为物理地址。
每个进程都有一个页表基址寄存器,用于存放该进程的页表首位地址。据此找到对应的页表首地址,然后根据虚拟地址的逻辑页号找到对应的页表项(两者数值上相加,可以理解为指针)。
CPU 访问页表的速度较慢,查询一次的时间相当于一次访存。因此,根据程序的局部性原理引入了快表(TLB) 机制,将近期访问的页表项放入快表。快表是基于 SRAM 的相联存储器,可以按内容访问,访问速度更快。
引入了 TLB 的完整地址变换过程如下图所示:
计算器拿到逻辑地址后,根据上面的逻辑页号去 TLB 查找,若未命中,则去访问页表。页表基址寄存器中的值与页号数值上相加得到对应表项在主存中的地址,从而查询到对应的主存块号,并将该页表项存入 TLB 中。主存块号与逻辑地址的页内地址拼接即可得到物理地址。
TLB 的整体实现原理与 Cache 类似,同样会涉及到映射方式和替换等问题。TLB 通常采用全相联或组相链映射方式。
TLB 的表项由页表表项内容和 TLB 标记构成。
查找时,快表和慢表也可以一起查询,若快表中有要查找的内容,则能很快找到对应的主存块号,并使慢表的查找作废,从而做到虽然采用虚拟存储器但访问主存速度几乎没有下降。
2.虚拟存储器
主存和辅存共同构成了虚拟存储器,二者在硬件和系统软件的共同管理下工作。对于应用程序员而言,虚拟存储器是透明的。虚拟存储器具有主存的速度和辅存的容量。
虚拟存储器也采用和 Cache 类似的技术,将辅存中经常访问的数据副本存放到主存中,但是缺页(或缺段)而访问辅存的代价很大,提高命中率是关键,因此虚拟存储机制采用全相联映射。此外,当进行写操作时,不能每次写操作都同时写回磁盘,因此,在处理一致性问题时,采用回写法。
(1)页式存储系统
页式虚拟存储器以页为基本单位。主存空间和虚拟地址空间被划分为大小相同的页,主存空间的页称为物理页、实页、页框,虚拟地址空间中的页称为虚拟页、虚页。页表记录了程序的虚页调入主存是被安排在主存中的位置。页表一般长久地保存在内存中。
以上图为例,页表中页表项各部分的含义如下:
-
有效位(装入位):这个页面是否已调入主存。1 表示已经调入主存,0 表示没有。
-
脏位(修改位):这个页面是否被修改过。1 表示被修改过,0 表示没有。
-
引用位(使用位):用来配合替换算法进行设置。
注意:缺页处理由软件完成,操作系统通过 “缺页异常处理程序” 来实现;而 TLB 缺失既可以用硬件,又可以用软件处理。
优点:页面的长度固定,页表简单,调入方便。
缺点:程序不可能正好是页面的整数倍,最后一页的零头将无法利用而造成浪费,并且页不是逻辑上独立的实体,所以处理、保护和共享都不及段式虚拟存储器方便。
(2)段式虚拟存储器
段式虚拟存储器中的段是按程序的逻辑结构划分的,各个段的长度因程序而异。把虚拟地址分为了两部分:段号和段内地址。段表的每行记录与某个段对应的段号、装入位、段起点和段长等信息。
因为段本身是程序的逻辑结构所决定的一些独立部分,因此分段对程序员来说是不透明的;而分页对程序员来说是透明的,程序员编写程序时不需要知道程序将如何分页。
优点:段的分界与程序的自然分界相对应,因此具有逻辑独立性,使得它易于编译、管理、修改和保护,也便于多道程序的共享。
缺点:段长度可变,分配空间不变,容易在段间留下碎片,不好利用,造成浪费。
(3)段页式虚拟存储器
段页式虚拟存储器把程序按逻辑结构分层,每段再划分为固定大小的页。程序对主存的调入、掉出仍以页为基本交换单位。每个程序对映一个段表,每段对应一个页表,段的长度必须是页长的整数倍,段的起点必须是某一页的起点。
虚地址分为段号、段内页号、页内地址三部分。CPU 根据虚地址访存时,现根据段号得到段表地址;然后从段表中取出该段的页表的起始地址,与虚地址段内页号合成,得到页表地址;最后从页表中取出实页号,与页内地址拼接形成主存实地址。
优点:兼具页式和段式虚拟存储器的优点,可以按段实现共享和保护。
缺点:在地址变换过程中需要查两次表,系统开销较大。
虚拟存储器与 Cache 的不同之处
- Cache 主要解决系统速度,而虚拟存储器确实为了解决主存容量。
- Cache全由硬件实现,是硬件存储器,对所有程序员透明;而虚拟存储器由 OS 和硬件共同实现,是逻辑上的存储器,对系统程序员不透明,但对应用程序员透明。
- 对于不命中性能影响,因为 CPU 的速度约为 Cache 的 10 倍,主存的速度为硬盘的 100 倍以上,因此虚拟存储器系统不命中时对系统性能影响更大。
- CPU 与 Cache 和主存都建立了直接访问的通路,和辅存于 CPU 之间没有直接同路。也就是说在 Cache 不命中时主存能和 CPU 直接通信,同时将数据调入 Cache;而虚拟存储器系统不命中时,只能先由硬盘调入主存,而不能直接和 CPU 通信。