计算机组成原理-存储系统

基本概念

  1. 层次结构

image.png

  • 注意:CPU是无法直接读取辅存中的数据的,需要先传输到主存中再进行读取,因为辅存的数据读取速度远远低于CPU。
  • 主存和辅存之间的交换需要硬件 + 操作系统,需要程序员进行判断哪些数据是需要交换的
  • cache 和主存之间的交换需要硬件,不需要程序员考虑。
  • 主存 - 辅存:实现了虚拟存储系统,解决了主存容量不足的问题。
  • cache - 主存:解决了主存和 CPU 速度不匹配的问题。

image.png

  • 虽然主存的读取速度已经很快了,但是还是远远比不上 CPU 的读取速度,因此我们可以使用 cache 存储主存中经常使用的数据,这样 CPU 可以直接读取 cache 中的副本数据。
  • 我们可以看到最上面一层是寄存器(CPU 中存储数据的单元),例如前面学到的 ACC 累加寄存器,MQ 乘商寄存器,而寄存器的读取速度又是要比 cache 快得多的。CPU 在进行加减乘除的运算的时候会将运算数放到寄存器中,而 CPU 内部包含的寄存器数量是非常有限的。
  • 注意:有些教材会将电脑内部的磁盘称为”辅存“,将 U 盘,光盘等称为”外存“,也有的教材将磁盘,U 盘,光盘等通称为”辅存“或”外存“。
  1. 分类
  • 按层次分类

image.png

  • 按存储介质分类
    1. 以半导体器件存储信息(主存,cache)
    2. 以磁性材料存储信息(磁带,磁盘)
    3. 以光介质存储信息(光盘)
  • 按照存取方式
    1. 随机存取存储器(Random Access Memory,RAM):读取任何一个存储单元的时间都是相同的,和所在的物理位置无关
    2. 顺序存取存储器(Sequential Access Memory,SAM):读取一个存储单元的时间取决于所在的物理位置
    3. 直接存取储存器(Direct Access Memory,DAM):先直接选取信息所在的位置,然后按顺序存取
    4. 相联存储器(Associative Memory),按照内容访问的存储器(Content Addressed Memory,CAM)按照内容检索到存储位置进行读写,快表就是一种相联存储器
  • 按照信息的可更改性
    1. 读写存储器(Read/Write Memory):即可读,也可写(磁盘,内存,cache)
    2. 只读存储器(Read Only Memory):只读不写(音乐专辑采用的CD-ROM,蓝光光碟)
  • 按照信息的可保存性
    1. 易失性存储器(主存,cache):断电后,存储信息消失的存储器
    2. 非易失性存储器(磁盘,光盘):断电后,存储信息仍然保存的存储器
    3. 破坏性读出(DRAM 芯片):读取数据后需要重写
    4. 非破坏性读出(SRAM芯片,磁盘,光盘),读取信息后信息仍存在
  1. 存储器的性能指标
  • 存储容量:存储字数 * 字长
  • 单位成本:总成本 / 总容量
  • 存储速度:数据传输率(主存带宽)= 数据的宽度 / 存储周期(存取时间不代表存储周期,存储周期 = 存储时间 + 恢复时间)

主存储器的基本组成

  1. 基本的半导体元件和原理

image.png
存储体是用来存储二进制数据的,每个存储体有多个存储单元构成,每个存储单元又是由多个存储元构成。
image.png

  • MOS管可以理解成为一种电控开关,输入电压达到某个阈值的时候,MOS 就会接通
  • 电容的一端接地意味着是 0 v,假如另一端存在一定的电压,电容中就会有电荷的存在,我们可以使用是否存在电荷表示数字 0 和 1

  • 读取操作中,当我们在 MOS 管处接入一个 5 v的电压,那么MOS 电路接通,电路的另一端可以检测到电流,我们读取到数字 1

image.png

  • 存储操作中,当我们在电路的另一端接入一个 5 v的电压,同时接通 MOS 管,那么电容的一端就会带电,同时断开 MOS 管,此时电容中就会存在电荷

image.png

  • 由于同属一个存储字的存储元它们的 MOS 管接的是同一根线,所以每次读或是写的单位都是读取一个存储字。
  1. 存储器芯片的基本原理

image.png

  • CPU 通过地址总线给出 MAR 地址,假设是 000 那么转换为十进制就是第 0 根字选线对应的位置,此时译码器将其转为该线的高电平信号,读取其中的每个存储元的数据后通过图中绿色的数据线将数据传送到 MDR 中,MDR 通过数据总线将数据再传送给 CPU。
  • 通过这个我们也可以知道 MAR 的位数对应了存储单元的个数,MDR 的位数对应了每个存储单元的存储字长。通过存储单元的个数和存储字长的乘积我们可以得到存储体的总容量,23 * 8bit = 8Byte = 8B

image.png

  • 由于地址总线和数据总线是通过电信号来传输数据的,而电信号通常是不稳定的,我们还需要控制电路对输入和输出进行控制,当我们的输入和输出的电压稳定后我们再开始进行译码器的工作或是数据总线中数据的传送。
  • 同时在控制电路外我们还需要对外提供一些线路,片选线(CS【Chip Select】 和 CE【Chip Enabled】),在图中的上划线代表在低电压情况下有效,当片选线接通低电压时意味着这个芯片已经接通可以工作。
  • 读控制线和写控制线分别控制着数据的写入和输出,我们可以使用两条控制线,也可以使用一条控制线,通过电压的高低来区分写和读。

image.png

  • 上图就是一个存储芯片的示意图,分为三大部分,其中译码驱动分为译码器和驱动器,其中译码器是向某条电路输入高电平,驱动器是为了保障电路的稳定起到对于电信号的放大作用

image.png

  • 上图中每一根线其实都会有一根金属引脚,也就是地址线 + 数据线 + 片选线 + 读写控制线(一条或者两条)
  • 对于存储芯片的描述我们可以使用例如 8K * 8位的方式,也就意味着有 8 k个存储单元,每个存储单元有 8 位,利用这个我们可以算出存储体的大小和存储体的位数
  1. 寻址

image.png

  • 我们可以按照字节寻址,按字寻址,按半字寻址,按双字寻址的方式进行寻址

SRAM和DRAM

  1. 定义:
  • DRAM(Dynamic Random Access Memory)动态 RAM
  • SRAM(Static Random Access Memory)静态 RAM
  • DRAM 用于主存,SRAM 用于cache
  1. DRAM 芯片
  • 两者的核心区别主要在于存储元的不同,DRAM芯片是使用栅极电容存储信息,SRAM 芯片是使用双稳态触发器存储信息

image.png

  • 栅极电容就是我们上面所学习的使用电容中的电荷进行判断 0 和 1

image.png

  • 双稳态触发器中我们使用两种状态对于 0 和 1 进行判断,1(A 高 B 低),0(A 低 B 高),因此我们可以根据两根数据线中谁读取的是低电平判断 0 和 1,同时我们也可以给左边数据线高电平,右边数据线低电平的方式实现 1 的写入。
  • 同时当我们读取栅极电容中的数据的时候,由于电容放电因此属于破坏性读取,需要重新写入数据,也称为”再生“,而对于双稳态触发器来讲,并没有破坏性,因此无需重写。
  • 一个需要重写,一个不需要重写,因此双稳态触发器的方式的读取速度更快
  • 由于 DRAM 芯片中存储元的制造成本更低,集成度更高,功耗更低,因此它的价格自然会低于 SRAM 芯片

image.png

  • 由于 DRAM 芯片使用的栅极电容由于电容本身的电荷会不断的流失,因此我们的数据仅仅可以保存 2 ms的可靠时间,需要不断地对于数据进行刷新防止数据出现错误,同时刷新操作是由存储器独立完成的,不需要 CPU 的控制
  1. DRAM 的刷新
  • 刷新周期一般为 2 ms
  • 以行为单位,每次刷新一行的存储单元

image.png

  • 由于当我们线路的数量级足够大的时候硬件的实现会变得非常困难,当我们有 220 根选通线的时候,也就是 1 M 根,这个数量是很大的,因此我们可以使用二维方式的设计,分为行和列。这样行或列仅需要 210 根线,也就是 1024 根。
  • 对于寻址操作,假如是一个八位的地址 0000 0000 我们将它分为两部分,分别为前四位 0000 在行地址译码器进行寻址,后四位 0000 在列译码器进行寻址
  • 刷新实现:通过硬件支持,读出一行的信息然后重新写入,占用一个读写周期
  • 三种刷新方式:(假设有128 * 128的排列方式,读取周期为 0.5 us)
    1. 分散刷新:每次读写完都刷新一次

image.png

  1. 集中刷新:留出一段时间集中用于刷新,这段时间无法访问存储器,称为”死区“

image.png

  1. 异步刷新:保证每一行都刷新一次,间隔一段时间刷新一次

image.png

  1. DRAM 的地址线复用技术

我们由于在上面已经将译码器分为了行地址译码器和列地址译码器,因此我们可以将行列地址分为两次送,这样可以使得地址线的数量更少,这样芯片的引脚也会更少

只读存储器 ROM

  1. 引入
  • RAM 芯片 – 易失性,断电后数据会消失
  • ROM 芯片 – 非易失性,断电后数据不会消失

image.png

  1. 各类 ROM
  • MROM(Mask Read - Only Memory)-- 掩模式只读存储器

厂家按照客户需求,在生产时直接写入,之后任何人都无法重写(只能读出),可靠性高,灵活性差,生产周期长

  • PROM(Programmable Read - Only Memory)-- 可编程只读存储器

用户可以自己写入数据,但是一次后无法更改

  • EPROM(Erasable Programmable Read - Only Memory)-- 可擦除的可编程只读存储器

允许用户写入信息,可以按照某种方法擦除数据(可以使用紫外线【UVEPROM】或电擦除【EEPROM】),可以多次重写

  • Flash Memory – 闪速存储器(U 盘,SD 卡就是闪存)

在EEPROM基础上发展而来,断电后也可以保存信息,可以进行多次快速擦除重写(由于需要先擦除在写入,因此写的速度慢于读的速度)

  • SSD(Solid State Drives)

由控制单元和存储单元(Flash芯片)构成,和闪存的区别在于控制单元不同,但是存储介质类似。

  1. 计算机中的ROM
  • 由于 RAM 中的数据在断电后就会丢失,因此我们需要将操作系统装到辅存中,为了引导系统从辅存中读取系统数据,我们需要将开机指令放在主板上的 BIOS 芯片(ROM),存储了”自举装入系统“,负责引导操作系统的开机。因此主存实际上是由内存条(RAM)和 BIOS芯片(ROM)共同构成的,在逻辑上二者也会有一个统一编址。
  • RAM 和 ROM 并不是相互对立的,实质上 ROM 也具有随机存取的特质。

双端口 RAM 和多模块存储器

  1. 引入

image.png
由于恢复时间长于存取时间,因此我们如果等待主存的恢复,那么一定会大大降低计算机的效率。因此我们可以使用双端口 RAM 和 多模块存储器

  1. 双端口 RAM

image.png

  • 两个端口同时对于一个主存进行操作存在下面 4 种情况
    1. 两个端口同时对不同的地址进行存取操作。(可行)
    2. 两个端口同时对相同的地址进行读操作。(可行)
    3. 两个端口同时对相同的地址进行写操作。(错误)
    4. 两个端口同时对相同的地址进行操作,一个写入数据,一个读出数据。(错误)

image.png

  • 上面的后两种情况发生时,需要给出”忙“信号,并且暂时关闭一个端口。
  • 作用:优化多核 CPU 对于同一根内存条的访问速度
  1. 多模块存储器

多模块存储器分为单体多字存储器,多体并行存储器
多体并行存储器

  • 多体并行存储器又分为高位交叉编址和低位交叉编址。
  • 高位交叉编址

image.png
首先计算存储单元的个数,由于有 4 * 8 = 32 = 25 个存储单元,因此我们可以使用 5 位二进制数进行地址的表示,对于高位交叉编制,我们将其前两位作为存储体的体号,后三位代表体内的地址。

  • 低位交叉编址

image.png
对于低位交叉编址来讲,我们可以将它的低位作为体号的编址,将高位作为体内地址的编址。

  • 我们可以看到上面两种编址方式的读取顺序是不同的,对于高位交叉编址,我们是按列读取每个存储单元,对于低位交叉编址,我们则是按行读取每个存储单元。
  • 设每个存储体的存储周期为 T,存取时间为 r ,我们假设 T = 4 r,接下来我们对于下面五个地址进行连续访问,00000,00001,00010,00011,00100

image.png

  • 对于这五个地址我们进行按列访问,总共将花费 5 T 的时间。

image.png

  • 对于低位交叉编址我们进行按列访问,我们可以看到由于我们避开了每个存储体的休息时间,因此我们可以大大提高读取的效率,当 n 的数量足够大时,我们读取每个存储单元的时间接近于 r。
  • 当存取周期为 T,存取时间(也可以称为总线的传输周期)为 r ,为了使流水线不间断,应该保证模块数 m >= T / r

单体多字存储器
image.png

  • 每个存储单元存储 m 个字,总线宽度也为 m 个字,一次并行读取 m 个字。
  • 每次同时读取 m 个字,无法单独读取其中的某个字,灵活性差,但是从宏观上看与多体并行存储的效率是相同的。

主存储器和 CPU 连接

  1. 首先我们介绍一下存储芯片中各种输入和输出信号的常用的一些英文缩写。

image.png

  • 在上图中,我们使用A0 - A7 代表地址线的从低到高位,使用D0 - D7 代表数据线的低位到高位。同时我们使用是否带有上划线判断是否是在低电平有效。
  1. 位拓展

image.png

  • 我们此时有一块 8K * 1 位的存储芯片,计算可知它的地址需要使用 13 位表示,8 K = 213,因此我们需要使用13 根数据总线,也就是对应了 A0 - A12,同时给 CS 一个高电平,使其正常工作。但是由于存储字长仅仅只有一位,因此我们仅连接 D0,为了提高效率,我们再加上一个存储芯片。

image.png

  • 可以看到,我们又加上了一块 8k * 1位的存储芯片,同时仍旧使用 A0 - A12的地址总线对其进行连接,使其可以同时执行读或写的操作,同时按顺序连接了 D1 数据总线,此时整个主存有了两块存储芯片,从整体上看,我们的存储字长也变成了两位。

image.png

  • 随着我们不断地进行位拓展,最终我们可以得到一个 8K * 8 位的主存储器。
  1. 字拓展

image.png

  • 现在我们给出一个 8K * 8 位的存储芯片,我们可以看到数据总线已经被完全使用,但是 CPU 上的地址总线并没有被完全使用,因此我们增加存储芯片的数量进行字扩展。

image.png

  • 我们按照上面的思路,将A0 - A12 这 13 根地址总线连接到 CPU 上,同时将 A13 和 A14 分别连接到两个存储芯片上的 CS 片选线上,我们分别给 A13 和 A14 不同的信号,由于高电平时芯片进行工作,因此当信号为 0 1 时,第二个芯片工作,当 1 0 时,第一个芯片工作。这种方法我们称为线选法,但是该方法具有很大的局限性。

image.png

  • 此时,我们仅将 A13 一条地址线分别与芯片一和芯片二接上,同时使用非门电路在芯片二的连线上,当信号为 1 时,芯片一工作,芯片二不工作,反之亦然。我们将这种译码器称为 1 - 2 译码器。

image.png

  • 根据前面所学,当输入端有 n 条线时,输出端将会有 2n 个片选信号。

image.png

  • 将输入端数量增加为 2 个,同理输出端(存储芯片)数量也需要增为 22 个。’

image.png

  • 根据对比,可以看到使用译码器选法可以使地址空间连续,更好的利用 CPU 的寻址能力,因此常常使用译码器片选法。
  1. 译码器补充

image.png

  • 上图是关于译码器的两种实现方式,左侧对应高电平有效的情况,右侧对其输出信号取反,对应低电平有效的情况。

image.png

  • 我们的译码器中还存在一个接口(EN),称为使能信号,类似于 CS 信号,上图中的三个使能信号,G1,G2A,G2B,控制着译码器的正常使用。CPU 中有 MREQ 接口连接着使能信号接口,CPU 可以对于译码器的生效起到控制作用。

磁盘存储器

  1. 外存储器

image.png

  • 外存储器也称为辅助存储器,目前主要使用磁表面存储器。
  1. 磁盘存储器
  • 存储区域

一块硬盘含有若干个记录面,每个记录面划分为若干个磁道,每个磁道又划分为的若干个扇区,扇区(也称为块)是磁盘读写的最小单位,也就是说磁盘按块存取。
image.png

  1. 磁头数(Heads):上图中黄线所指位置为记录面,表示硬盘总共的磁头数,磁头用于读取记录面上的信息,一个记录面对应一个磁头。
  2. 柱面数(Cylinders):上图绿线所指为磁道,不同记录面的磁道组成一个圆柱面。
  3. 扇区数(Sectors):上图橙线所指为扇区数,表示每个磁道上有多少个扇区。
  • 硬盘存储器

硬盘存储器由磁盘驱动器(核心部件是磁头组件和盘片组件),磁盘控制器(硬盘存储器和主机的接口),盘片组成。

  1. 性能指标
    1. 磁盘的容量:一个磁盘所能够存储的字节总数称为磁盘容量,磁盘容量有非格式化容量(磁记录表面可以使用的磁化单元总数)和格式化容量(按照某种特定格式存储的信息总量)之分,因此格式化的容量实际上要小于非格式化的容量。

image.png

  1. 记录密度:盘片单位面积上记录的二进制的代码量,常常以道密度(沿磁盘半径方向上单位长度的磁道数),位密度(磁道单位长度上记录的二进制位数),面密度(位密度和道密度的乘积)表示。

image.png

  1. 磁盘所有磁道的记录数一定是相等的,并不是与圆越大信息越多,因此每个磁道的位密度都不相同。

image.png

  1. 平均存取时间:寻道时间(磁头移动到目的磁道)+旋转延迟时间(磁头定位到所在扇区)+传输时间(传输数据所花费的时间)
  2. 数据传输率:磁盘存储器在单位时间内向主机传送数据的字节数,称为数据传输率。假设磁盘转数为 r(转/秒),每条磁道的容量为 N 个字节,数据传输率为 Dr = rN
  3. 磁盘地址
  • 磁盘地址一般为:

image.png

  1. 硬盘的工作过程
  • 磁盘的主要操作是寻址,读盘,写盘,每个操作都对应一个控制字,硬盘工作时,首先取出控制字,接着执行控制字。
  1. 磁盘阵列
  • RAID(Redundant Array of inexpensive Disks)将多个独立的物理磁盘组成一个独立的逻辑盘,数据在多个物理盘上交叉存储,并行访问,具有更好的存储性能,可靠性和安全性。

image.png

  • 除RAID0 外,从RAID1 到 RAID5 数据的冗余性逐渐降低,安全性,可靠性逐渐提高,成本也在逐渐减少。

image.png

固态硬盘 SSD

  1. 基本结构

image.png

  • 上图中左侧是前面学习的机械硬盘,右侧是将要学习的固态硬盘。

image.png

  • 原理

基于闪存技术,属于电可擦除ROM(EEPROM)。

  • 组成:

固态硬盘的基本结构如上图所示,以一个页为基本单位,相当于是磁盘存储器中的每个扇区(也称为块),每个页的大小是 512B ~ 4KB,同时可以将每个闪存芯片中的块看作磁盘中的磁道。

  • 读写特性:
  1. 在进行读写时,固态硬盘是以页为单位读/写,以块为单位擦除,已经擦除的块,其中每一页都也可以写一次,读无限次(向非空页中写入数据时,需要先进行擦除),如果要写的页中有数据,需要先擦除。
  2. 擦除过程中需要先将块中的数据复制到一个新的(已经擦除过的块),再进行擦除。
  • 与机械硬盘相比:
  1. 固态硬盘支持随机访问,通过指定逻辑地址,根据电路迅速定位到相应的物理地址。
  2. 固态硬盘的一个块如果被擦除的次数过多,会导致这个块产生损坏。
  3. 固态硬盘安静无噪音,耐摔抗震,能耗低,造价贵。
  • 磨损均衡技术:

将擦除均匀的分在每个块上,提高使用寿命

  1. 动态磨损擦除:写入数据时,优先选择累计擦除次数更少的块。
  2. 静态磨损擦除:SSD 检测并进行数据的分配,迁移,让老旧的闪存块承担以读为主的存储任务,较新的闪存块承担更多的写任务。

Cache 基本概念和原理

  1. 引出

为了缓和 CPU 和主存之间的速度矛盾,因此,我们使用 Cache 作为中间层,Cache 被集成在 CPU 内部,Cache 使用 SRAM 实现,速度快,成本高。

  1. 局部性原理

image.png

  • 这是一个数组的循环遍历函数,属于按行访问的顺序。

image.png

  • 通过上面的程序运行图,我们可以看到程序在空间和时间上具有局限性
  • 空间局限性:在最近的未来要用到的信息(指令和数据),很可能与现在正在使用的信息在存储空间上是邻近的(例如:数组元素,顺序执行)
  • 时间局限性:在最近的未来要使用到的信息,很有可能是现在正在使用的信息。(例如:循环结构)
  • 根据局部性的原理我们可以将目前 CPU 访问的地址周围的部分数据放入 cache 中

image.png

  • 该程序使用了按列访问,因此它的空间局部性不好,因此该程序的运行速度有可能低于程序 A
  1. 性能分析
  • 设 tc 为访问一次 Cache 所需要的时间,tm为访问一次主存需要的时间,
  • 命中率 H :CPU 想要访问的信息已经在 Cache 中的比率
  • 缺失率 M :M = 1 - H
  • 系统的平均访问时间:
    1. t = H*tc + (1-H)(tc + tm),先访问 Cache,若Cache 未命中在访问主存
    2. t = Htc + (1-H) tm同时访问 Cache 和主存,若 Cache 命中则立即停止访问主存
  1. 分块处理
  • 基于局部性原则,我们可以将 CPU 周围的数据放入 Cache 中,为了对于周围进行界定,我们引入了块这个定义。
  • 将主存进行分块,例如:每 1KB 一块。主存和Cache 之间以”块“的形式进行数据交换。

image.png

  • 例如一个 4 MB 的主存,我们将它按照 1KB 一块进行分可以将其分为 212 = 4096块,此时我们可以用 22 位来表示主存地址,以前 12 位为块号,后 10 位为块内地址。
  • 注意:操作系统中,通常会将主存中的”一个块“也称为”一个页/页面/页框“,将 cache 中的”块“称为“ 行 ”。

Cache 和主存的映射方式

  1. 三种映射方式
    1. 全相联映射:主存块可以放在 Cache 的任何位置。

image.png

  1. 直接映射:每个主存块仅可以放在一个特定位置。( Cache 块号 = 主存块号 % Cache 总块数)

image.png

  1. 组相联映射:Cache 块分为若干组,每个主存块可以放到任意的一个地方。(组号 = 主存块号 % 分组数)

image.png

  • 为了区分 Cache 块中放的是那个主存块,可以为每一个 Cache 添加一个标记,记录对应的主存块号。由于计算机每个 Cache 的初始状态全为 0 ,因此我们还需要使用有效位对其进行标记。

image.png

  1. 全相联映射(任意放)
  • 假设某个计算机的主存地址空间大小为 256MB,按字节编址,其数据 Cache 有 8 个 Cache 行(即 Cache 块,与主存块的大小相等),行长为 64 B 。按照上面所学的编制方法,可以将主存中的地址分为 28 位,256 M = 228,其中由于每块的大小为 64 B,64 B = 26,因此我们共可以分为228 / 26 = 222 个主存块。因此使用 22 位作为主存块号。

image.png

  • CPU 访问主存地址:1 … 1101 001110
    1. 首先将该地址的前 22 位与 Cache 中的标记进行匹配。
    2. 如果成功匹配并且有效位为1,那么按照后 6 位的地址从 Cache 中取出数据。
    3. 如果没有匹配成功或者有效位数为 0 ,则从主存中访问数据。
  1. 直接映射
  • 假设某个计算机的主存地址空间大小为 256MB,按字节编址,其数据 Cache 有 8 个 Cache 行(即 Cache 块,与主存块的大小相等),行长为 64 B 。采用直接映射的方式,主存块在 Cache 中的位置 = 主存块号 % Cache 总块数。
  • 由于上述取余计算之后得到的数据只有主存块号的后三位,因此我们仅仅通过后三位数字就可以知道该主存块在 Cache 中的映射位置,例如0 … 0 000 和0 … 1 000 在 Cache 中的映射位置是相同的,都位于 0 号位置。因此我们可以将主存块号中的数据进行再次细分。

image.png

  • CPU 访问主存地址:1 … 1101 001110
    1. 首先根据主存块号的后 3 位确定 Cache 行
    2. 若 Cache 的标记位与主存块号的前 19 位相同,并且有效位 = 1,那么按照后 6 位的地址从 Cache 中取出数据。
    3. 如果没有匹配成功或者有效位数为 0 ,则从主存中访问数据。
  1. 组相联映射
  • 假设某个计算机的主存地址空间大小为 256MB,按字节编址,其数据 Cache 有 8 个 Cache 行(即 Cache 块,与主存块的大小相等),行长为 64 B 。采用组相联映射,组号 = 主存块号 % 分组数。
  • 那此处采用 2 路组相联映射 – 2块为 1 组,分为 4 组。(主存块号 % 22)

image.png

  • 由于上述取余计算之后得到的数据只有主存块号的后两位,因此我们仅仅通过后两位数字就可以知道该主存块在 Cache 中的映射位置,例如0 … 00 01 和0 … 11 01 在 Cache 中的映射位置是相同的,都位于第一组。因此我们可以将主存块号中的数据进行再次细分。

image.png

  • CPU 访问主存地址:1 … 1101 001110
    1. 首先根据主存块号的后 2 位确定 Cache 中的分组
    2. 若 Cache 的标记位与主存块号的前 20 位相同,并且有效位 = 1,那么按照后 6 位的地址从 Cache 中取出数据。
    3. 如果没有匹配成功或者有效位数为 0 ,则从主存中访问数据。

Cache 替换算法

  1. 引出
  • 由于 Cache 很小,主存很大,因此我们需要考虑当 Cache 中填满的情况,需要注意的是,每次被访问的主存块,一定会被立即调入 Cache 中。
  1. 使用情况
    1. 全相联映射:对这种映射方式,我们需要在 Cache 完全满了之后才全局选择需要替换那一块。
    2. 直接映射:如果对应位置非空,则需要毫无选择的直接替换。
    3. 组相联映射:分组满了之后需要在分组中选择需要替换的块。
  • 因此替换算法只会在全相联映射和组相联映射中使用。
  1. 随机算法(RAND)
  • 随机算法(RAND,random)-- 若 Cache 已满,则随机选择一块进行替换。
  • 设总共有 4 个 Cache 块,初始化整个 Cache 为空,采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}

image.png

  • 实现简单,但完全没有考虑局部性原理,命中率低,实际效果很不稳定。
  1. 先进先出算法
  • 先进先出算法(FIFO,First In First Out)-- 若 Cache 已满,则替换最先被调入的 Cache 块。
  • 设总共有 4 个 Cache 块,初始化整个 Cache 为空,采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}

image.png

  • 实现依旧简单,最开始按 #0#1#2#3 放入Cache 中,之后进行依次替换 #0#1#2#3。但是该算法依旧没有考虑局部性原理,最先调入的块也有可能会被频繁访问。
  • 抖动现象:频繁的发生换入换出现象,刚被换出的块接着又被调入。
  1. 近期最少使用算法(LRU)
  • 近期最少使用算法(LRU,Least Recently Used)-- 为每一个 Cache 块设置一个计数器,用于记录该 Cache 块已经多久没有被访问了,当 Cache 满后替换“计数器”最大的。
  • 设总共有 4 个 Cache 块,初始化整个 Cache 为空,采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}

image.png

  • 使用方式:
    1. 命中时,所命中行的计数器清零,比其低的计数器加 1 ,其余保持不变。
    2. 未命中且有空闲行,新加入的行的计数器为 0 ,其余非空闲行全部加 1 。
    3. 未命中且无空闲行,计数器最大的行的信息块被淘汰,新装入的块的计数器为 0 ,其余全部加 1 。
  • 采用这种方式,当 Cache块的个数为2n时,计数器的位数仅仅需要 n 位,并且使用这种方法计数器一定不会出现重复。
  • 该算法基于局部性原理,根据时间局部性,近期访问的数据在不久的将来也有可能会被访问,因此该算法的运行结果优秀且命中率高。
  • 但如果被频繁访问的主存块的个数 > Cache 行的个数,就有可能发生抖动现象。如(1,2,3,4,5,1,2,3,4,5,1 … )对上面四个 Cache 块进行访问。
  1. 最不经常使用算法
  • 最不经常使用算法(LFU)-- 为每一个 Cache 块设置一个计数器,用于记录每个 Cache 块被访问过几次,当 Cache 满后替换计数器最小的。
  • 设总共有 4 个 Cache 块,初始化整个 Cache 为空,采用全相联映射,依次访问主存块{1,2,3,4,1,2,5,1,2,3,4,5}

image.png

  • 新调入的块的计算器 = 0,之后每一次被访问计数器 +1,需要进行替换时,先择计数器最小的一行。
  • 当发生同时存在最小的情况时,可以采用按行号递增或 FIFO 的规则进行排序。
  • 该算法并没有个很好的遵循局部性原则,曾经被经常访问的主存块在未来并不一定经常使用(例如,我们的微信聊天程序调用的程序在未来并不一定经常使用)

Cache 写策略

  1. 引入

在 CPU 修改了 Cache 中的数据副本后,如何保证主存中数据的一致性

  1. 写命中
  • 当 CPU 对 Cache 写命中时,为了保证数据的一致性,有两种方法。
    1. 写回法
  • 当命中时,仅仅对于 Cache 中的值进行修改,不立即写入主存中,只有当这块 Cache 被替换时才写回主存。同时为了区分需要写回的 Cache 块,我们又加上了脏位对其进行标记。
    2. 全写法
  • 也称为写直通法,当命中时,需要把数据同时写入 Caceh 和主存中。我们一般使用写缓存的方式。

image.png

  • 我们使用一个使用 SRAM 实现的 FIFO 队列,我们将需要写入主存中的数据先写入这个队列中,假设当 CPU 的写操作停止时,进行读操作,那么可以在专门的电路控制下将该队列中的数据写回主存中。
  • 如果 CPU 写的操作不频繁,使用该方法的效果很好,但是如果写的操作过于频繁,可能会发生写缓冲队列发生拥堵的现象。
  1. 写不命中
  • 当 CPU 对 Cache 写不命中时,为了保证数据的一致性,有两种方法。
    1. 写分配法
  • 当 CPU 对于 Cache 写不命中时,先将主存块调入 Cache,接着在 Cache 中进行修改,通常搭配写回法进行使用。
    2. 不写分配法
  • 当 CPU 对于 Cache 写不命中时,直接在主存中进行修改,通常搭配全写法进行使用。
  1. 多级 Cache
  • 现代计算机常使用多级 Cache,离 CPU 越近,速度越快,容量越小,离 CPU 越远,速度越慢,容量越大。

image.png

页式存储器

  1. 引入image.png
  • 由于一个程序的存储大小可能会过大,为了避免在存储中连续的存储过大的存储内容,因此将一个程序分为几个"页",每个页的大小和主存中’物理块’的大小相同。
  • 页式存储系统:一个程序(进程)在逻辑上被分为若干个大小相同的"页面","页面"大小和"块"的大小相同,每个页面都可以离散的放到不同的主存块中。
  1. 虚地址 vs 实地址
  • 逻辑地址(虚地址):程序员视角看到的地址
  • 物理地址(实地址):实际在主存中的地址
  • 例如当前有一个 4KB = 212 B的程序,该程序的地址范围是 00 0000000000 ~ 11 1111111111

image.png

  • 假设在其中有两个变量分别为x,y。两个变量的逻辑地址如上图所示,当我们在进行取值时,操作系统会将这个逻辑地址映射为对应的物理地址。

image.png

  • 其中最重要的是将其逻辑页号映射为对应的主存块号。

image.png

  • 为了记录这种映射关系,操作系统会创建一个页表,该页表会记录每个逻辑页面存放在那个主存中。

image.png

  • CPU执行的机器指令中,使用的是”逻辑地址“,因此通常需要”页表“将逻辑地址转换为物理地址。页表数据存放在主存中,因此 CPU 在进行一次地址转换的时候需要查询页表,也就意味着 CPU 需要进行一次访存的操作。

image.png

  • 当 CPU 访问一个逻辑地址时,首先将其分为逻辑页号和页内地址,根据 CPU 中的页表寄存器找到页表地址,查找到逻辑页面存放的主存块,最后将主存块和页内地址进行拼接得到需要访问的物理地址。

image.png

  • 我们根据在访问主存时,由于程序本身具有局限性,因此我们可以使用 Cache 存储高频访问的信息,我们可以得到一个类似的方法。我们在地址变换过程中加上一个快表,当我们进行访问时,首先访问快表,如果没有命中就仍然按照之前的方式。
  • 快表中存储的是页表项的副本,Cache 中存储的是主存中的副本。
  • 快表是一种”相联存储器“,可以按照内容寻访,同时是采用SRAM存储,效率快于采用DRAM存储的页表。

虚拟存储器

  1. 引入

image.png

  • 当我们在启动一个应用程序的过程中,没有必要将所有的数据全部从辅存中调入主存中,因此可以调入其中的一部分即可。因此仅仅只有 4GB的主存却可以同时运行远远超过 4GB 的程序,这种虚拟现象也被称为虚拟存储器。
  1. 页式虚拟存储器

image.png

  • 我们可以将调入的程序进行分页操作,将需要调入的部分先调入主存中。
  • 在辅存中的数据调入主存的过程中,我们需要对页表上添加一些属性。
    1. 外存块号:将辅存进行分块,需要调入时直接调入该块数据。
    2. 有效位:记录是否已经调入主存。
    3. 访问位:记录调入主存中数据的访问次数。
    4. 脏位:记录调入主存中的数据被是否被修改。
  1. 段式虚拟存储器

image.png

  • 按照功能模块对其进行拆分,每一段的大小不同。 按照段式存储时,主存不会按页划分。
  1. 段页式虚拟存储

image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值