3.存储系统
存储系统
基本概念
存储系统层次化结构
Cache指的是高速缓冲存储器
主存和辅存之间的交换涉及到了操作系统中的虚拟存储系统部分,解决了主存容量不够的问题
而Cache和主存之间的交换解决了主存与CPU速度不匹配的问题
存储器的分类
按层级分:可以分为高速缓存(Cache),主存储器(内存),辅助存储器(外存,磁盘)
按存储介质分:半导体存储器(主存,Cache),磁表面存储器(磁盘,磁带,硬盘),光存储器(光盘)
按存储方式分:
- 随机存取存储器 RAM(Random Access Memory):即是读写任何一个存储单元所需时间都相同,与存储单元所在物理位置无关,比如内存条
- 顺序存取存储器(Sequential Access Memory,SAM):读写一个存储单元所需时间取决于存储单元所在的物理位置,比如磁带
- 直接存取存储器(Direct Access Memory,DAM):既有随机存取特性,也有顺序存取特性。先直接选取信息所在区域,然后按顺序方式存取,比如硬盘
- 相联存储器(Associative Memory),即可以按内容访问的存储器,(Content Addres Memory)CAM,比如快表
按信息的可更改性:读写存储器(磁盘,内存)只读存储器(CD)
按信息的可保存性:
- 断电后,存储信息消失(主存,Cache)
- 断电后,存储信息存在(磁盘,光盘)
- 信息读出后,原存储信息被破坏(DRAM芯片)
- 信息读出后,原存储信息不被破坏(SRAM芯片,磁盘)
存储器的性能指标
存储容量:存储字数×字长
单位成本:每位价格=总成本/总容量
存储速度:数据传输率(主存带宽 )=数据的宽度/存储周期
因为每次存储结束后,存储器需要一定的时间恢复,所以存储时间和存储周期之间是有差别的
主存储器的基本组成
基本的半导体元件
以下知识将大量涉及到数电,所以将简要描述知识点(数电里学过了)
MOS管和电容可以组成一个基本的存储元,来表示0和1
而多个存储元集中排列在一起,则形成了基本的存储单元,就是存储字
而多个存储字会拼接会形成一个存储体
而操纵这个存储体所需要的器件,就是译码器
存储体芯片的基本原理
译码器的作用是将MAR的中的地址信号,传达到具体的存储单元中去
比如MAR中是3位地址,那么译码器会有$2^3=8$条线,连接到具体的存储单元中去,当某一条字选线接通的时候,存储字中的信息就会被存储在MDR中,通过数据总线传输到CPU
需要一个控制电路来保持MAR和MDR中电信号稳定,同时还要有片选线,表示控制电路何时可用,同时还要有读控制线和写控制线,可以用两根线来读和写,也可以用一根线来读和写
总得来说,整体结构如下
因为一个内存条里面有多块存储芯片,所以需要片选线来指定具体的存储芯片
而芯片上的金属引脚,就是用来连接地址线,片选线,数据线,读写控制线等的
SRAM和DRAM
DRAM(Dynamic Random Access Memory):动态RAM
SRAM(Static Random Access Memory):静态RAM
区别
- 利用MOS管作为存储元的RAM就是DRAM,SRAM使用的是双稳态触发器作为存储元
- DRAM在读出数据时会破坏性读出数据,读出后应有重写的操作,而SRAM在读取数据后不会被破坏,读写数据更快
- DRAM每个存储元制造成本低,集成度高,功耗低 ,SRAM的成本高,功耗高
SRAM常常用于Cache,而DRAM常用于主存
DRAM的刷新
刷新是指电容内的电荷只能维持2ms,所以DRAM需要不断的刷新,每次刷新一行存储单元,地址常常是二维的,译码器分为行译码器和列译码器
刷新操作有硬件支持,读书一行数据后重新输入,占用1个读写周期,不需要CPU控制
刷新方法有3种
分散刷新
每次读写完刷新一个行,将一个存取周期的前一半时间正常读取,后一半时间刷新某行
集中刷新
在2ms内集中安排一个时间刷新,在此期间无法访问存储器,称为死区
异步刷新
2ms内每行需要刷新一次,每隔固定的时间刷新一行,可以在译码阶段刷新
DRAM有地址线复用技术,可以将地址分两次传送,只需要n/2条地址线就能完成地址的传输
只读存取器ROM(Read-Only Memory)
ROM芯片具有非易失性,断电后数据不会丢失
MROM(Mask Read-Only Memory)——掩模式只读存储器
厂家在生产的时候直接写入,之后只能读出,任何人不能改写
PROM(Programmable) ——可编程只读存储器
可以用专门的写入器写人信息,写一次后不可更改
EPROM(Erasable Programmable)——可擦除可编程只读存储器
允许用户写入信息,之后用某种方法擦除数据,可进行多次重写
Flash Memory ——闪存(u盘)
由EEPROM发展而来,断电后也能保存信息,可进行多次快速的擦除重写,由于闪存需要先擦除后写入,因此闪存的写比读更慢
SSD(Solid State Drives)——固态硬盘
有控制单元+存储单元(Flash芯片)构成,在闪存的区别在于控制单元不一样,存储介质一样,可以进行多次快速擦除重写,速度快,功耗低,价格高
BIOS芯片中存储了自举装入程序,负责引导装入操作系统
尽管ROM的名字是“Read-Only”,但实际上,很多的ROM也可以 写(u盘)
很多ROM同样具有随机存取的特点
主存储器和CPU的连接
单块存储芯片和CPU的连接
如果想拓展存储体中的字数,需要用到字拓展法
如果想拓展数据总线的宽度,需要用到位拓展法
字拓展法
增加主存的存储字数,可以使用多个存储芯片,将多余的CPU的引脚来控制存储芯片的激活,即线选法,n条线输出n个选片信号
而在n条线之后添加译码器,可以输出$2^n$个选片信号,称为片选法
区别如下:
位拓展法
增加主存的存储字长,可以用多块存储芯片,将数据总线连接到不同芯片中,将1位芯片扩展到8位
字位同时拓展
使用多块存储芯片为1组,同时使用译码器来同时实现字位拓展
双端口RAM和多模块存储器
DRAM芯片的恢复时间很长,而现代计算机通常是多核CPU,多核CPU之间存在访存问题
双端口RAM
即指RAM提供2个端口,方便两个CPU同时访问,须有有两组完全独立的数据线,地址线,控制线,电路也更复杂
目的就是为了优化多核CPU访问一根内存条的速度
两个端口可以同时对内存的不同地址单元进行读取,也可以对同一地址单元读出数据,但是不能同时对同一地址单元写入数据,也不能对同一地址单元同时读入和写入数据
解决办法:可以设置一个信号,由逻辑判断决定暂时关闭一个端口,被关闭的端口延后访问
多模块存储器
为了提高存储器和CPU之间的速度,可以采用多体并行存储器
多体存储器分为高位交叉编址和低位高位编址,区别在于将内存条的某几位作为地址进行编址的位置的不同
可以看到,连续的地址由于低位交叉编址,被分配在了不同的内存条中,可以大大减少访问连续地址时的等待时间
假设每个存储体的存取周期是T,存取时间是r,那么连续存取n个字,耗时是T+(n-1)r
为了保证存取的顺畅性,应保证模块数m=T/r
双通道:即指的是两个内存条之间采用低位交叉方式进行编址
单体多字存取器可以将存储器集合在一起,每次读取多个字,相当于位拓展
Cache
基本概念和原理
Cache即是高速缓冲存储器,由SRAM组成,负责加快内存和CPU之间的数据传输
假设$t_c$为访问一次Cache所需时间,$t_m$为访问一次主存所需时间
命中率H:CPU访问的信息在Cache中的比率
缺失率: M=1-H
如果先访问Cache,未命中再访问主存,那么平均访问时间是$t=Ht_c+(1-H)(t_c+t_m)$
如果同时访问Cache和主存,若Cache命中就立即停止访问主存,那么平均访问时间是$t=Ht_c+(1-H)(t_m)$
(以下内容和操作系统的存储管理有极大联系)
为了实现将主存与Cache之间的数据交换,可以将主存的存储空间分块,主存与Cache之间以块为单位进行数据交换
假如主存的地址是4M,也就是$22$位,其中前12位标记为块号,后10位标记为块内的地址,整个主存被分为$2^{12}=4096$块,每一块包括有1K个地址
一块又称为一个页,或页面,而Cache中的块也被称为行,Cache的块的大小和主存中块的大小保持一致
Cache和主存之间的映射
- 直接映射
直接映射,即是主存块在Cache中的位置=主存块号%Cache总块数
假设Cache的总块数是$2^3$,则相当于保留下主存块号的后3位,若Cache的总块数为$2^{n}$,则主存块的末尾n位直接反映了它在Cache中的位置,将主存块号的其他位置作为标记即可
标记的作用是指明Cache中块数对应的内存块数
CPU访问内存地址的步骤:
- 根据主存块号的后三位确定Cache行
- 若主存块号的前19位和Cache标记匹配,且有效位为1,说明Cache命中,则访问块内地址为主存块内地址的单元
- 若未命中,则正常访问主存
- 全相联映射
也就是说,主存中的块可以随意放到Cache中去,放入后,将Cache块的标记改为主存地址即可
CPU访问内存地址步骤:
- 主存地址的前22位对比Cache中所有块的标记
- 若标记匹配且有效位为1,则访问块内地址为主存块内地址的单元
- 若未命中,则正常访问主存
- 组相联映射
组相联映射,所属分组=主存块号%分组数
分组数为$2^{n}$,则主存块的末尾n位直接反映了它在Cache中分组的位置
CPU访问内存地址的步骤:
- 根据主存块号的后2位确定所属分组号
- 若主存块号的前20位和Cache标记匹配,且有效位为1,说明Cache命中,则访问块内地址为主存块内地址的单元
- 若未命中,则正常访问主存
替换算法
对于全相联映射,当Cache满了之后,需要在全局中选择替换一块
对于直接映射,当Cache满了之后,可以直接替换掉
对于组相联映射,当Cache分组内满了之后,才需要在分组内选择替换哪一块
所以对于全相联映射和组相联映射,需要替换算法以判断替换的块数
- 随机算法(RAND)
如果Cache满了,则随机选择一块进行替换,虽然实现简单,但Cache的命中率会很低
- 先进先出算法(FIFO)
若Cache已满,则替换最先被调入的块,实现简单,但仍然没考虑到局部性原理
- 近期最少使用算法(LRU)
为每一个Cache块设置一个计数器,用于记录每个Cache块已经有多久未被访问了,当Cache满后替换掉计数器最大的
计数规则如下:
- 命中时,将所命中行计数器清零,比其低的计数器加1,其余不变
- 未命中且还有空闲行时,新装入的行计数器置0,其余非空闲行全加1
- 未命中且无空闲行时,计数器最大的信息块被淘汰,新装行的块计数器置0,其余全加1
之所以命中时比命中行高的计数器不变,是因为加1了之后没有意义,而且可以用较少的比特位来表示计数器状态,假如Cache块的总数是$2^n$则计数器只用n位,而且Cache装满后,所有计数器的值一定不重复
这种算法的命中率高,算法性能优秀
- 最不经常使用算法(LFU)
为每一个Cache块设置一个计数器,用于记录每个Cache块被访问过几次,当Cache块满后替换计数器最小的
新调入的块计数器为0,之后每被访问一次计数器+1,替换时,选择计数器最小的一行
若有多个计数器最小行,可以按其他策略来选择被替换的行,实际上性能不如LRU
Cache写策略
CPU修改了Cache中的数据后,需要保证Cache和内存中的一致性
- 写回法
如果Cache对Cache写命中了,只修改Cache的内容,而不立刻写入主存,只有当此块被换出后才写入主存
需要设置一个标志位来表示该行是否被修改过
- 全写法
如果Cache对Cache写命中了,同时修改Cache和主存中的内容,可以保证数据的安全,一般使用写缓冲(write buffer)的方法
即用SRAM制造一个缓存器,实现FIFO的功能,如果要修改Cache,CPU将要修改的主存内容写入到缓存器中,然后由专门的控制电路控制写缓冲器写回到主存中去
使用写缓冲时,CPU写的速度很快,当写操作很频繁的时候,可以会发生阻塞
- 写分配法
当CPU对Cache没有命中,则把主存中的块调入到Cache中进行修改,通常搭配写回法
- 非写分配法
当CPU对Cache没有命中,则对主存中的数据直接进行修改,通常搭配全写法
现代计算机通常采用多级Cache,越接近CPU的Cache速度越快,容量越小
Cache和Cache之间常采用全写法和非写分配法,而Cache和主存之间使用写回法和写分配法
页式存储器
只介绍其和Cache的联系,具体看操作系统第三章