前言

目前正在备考 24 考研,现将 24 计算机 408 学习整理的知识点进行汇总整理。

博主博客文章目录索引:博客目录索引 (持续更新)

一、存储器概述

1.1、层次结构

寄存器包含 ACC、MQ 等,速度要比 cache 快得多。

  • 主存与辅存之间的数据交换是由系统程序员来处理,其中操作系统中包含页面置换算法。
  • Cache 与主存之间的数据交换是硬件自动完成的,软件程序员无需关心之间的数据交换,这部分是由硬件工程师实现的。

此时由于这种关系,应用程序员所看到的主存通常较大,下面是主存 - 辅存、Cache - 主存解决的问题

各层存储器的速度与价格:光盘 机械硬盘 固态硬盘 内存条

  • 速度由低到高,价格也是由低到高

1.2、存储器分类

1.2.1、层次分类

1.2.2、存储介质分类

①半导体存储器:如主存、Cache

②磁表面存储器:软盘、磁带、机械硬盘(下图从左到右)

③光存储器:光盘、DVD、VCD 都是光存储器

1.2.3、存取方式

①随机存储器,如内存条:访问指定地址的时间都是一样的

②顺序存取存储器:复读机中放的磁带

若是需要读取磁盘中的某一块内容,则需要等待磁头转到那边

③直接存取存储器

例如机械硬盘、磁盘都是典型的直接存取存储器,既有随机存取的特性,又有顺序存取特性。

首先磁头臂会进行前后的移动到想要读取的区域,接下来会有个磁盘,不断滑动,这个磁盘就可以相应的读和写。

存取速度 (小到快):顺序存储存储器 直接存取存储器 随机存取存储器。

④相联存储器:根据根据要找的内容,直接去寻找内容对应在哪里。

不同:①-③根据地址访问、④根据内存访问。

1.2.4、按照信息的可更改性(读写、只读区别)

1.3、存储器性能指标

①存储容量存储字数x字长(如 1M x 8 位)

  • MDR 位数反应存储字长。MAR 反应存储字数。

②单位成本每位价格=总成本/总成本,每个 bit 位付出的金钱成本。

举例:

③存储速度数据传输率=数据的宽度/存储周期,数据的宽度即存储字长

  • 一个存储周期可以读或写一个存储字这么多的数据。
  • 存取周期则见如下:

知识回顾

二、主存储器

2.1、主存储器的基本组成(介绍 DRAM)

2.1.1、主存储器的基本元件

主存储器分为存储体、MAR(地址寄存器)、MDR(数据寄存器)三个部分:

这三个部分会在时序控制逻辑电路中相互配合使用:

  • 一个存储体由多个存储单元构成 每个存储单元由多个存储元构成 使用一个存储元件可以存放一个二进制位的 0 或 1

  • 给 MOS 管一个阈值电压(5v)就能够导电,若是不给那么就是一个绝缘体不会导电。

2.1.2、存储芯片的基本原理

基于上面的存储元来介绍下读出、写入原理:

  • 读出二进制原理:通常在电容中保存着数据 0 或 1,那么如何去读取呢?可以给 MOS 管加电流,若是达到阈值 5V,此时右端就会流出 1,否则就会流出 0。
  • 写入二进制原理:可以在 MOS 管的右端加一个 5v 的高电平,同时也给 MOS 管加一个 5v 的电平,此时 MOS 管就可以接通,电容中就会存储 1,此时 MOS 管端口,电容里的电荷就跑不出去了。

如何读取多个存储二进制值呢,通过去读取存储单元来进行,如下,由多个存储元组成的一个存储单元,在存储单元上每个 MOS 管接线,若是想要读取一组单元的存储元值,直接全部上电压,就能够读取到一个存储单元的所有二进制位 (每个存储元中的电容)。

  • 此时由多个存储单元组成就是一个存储体。

如何根据地址来决定我们要读或者写哪个存储字呢

  • 此时涉及到译码器的使用,译码器会根据 MAR 中给出的几个地址转变为指定某条线的高电平信号。
  • 每个地址都会对应译码器的一条线。
  • 一个地址信号可以被转换成译码器的某一条输出线的高电平信号,一旦这一条字选线被接通之后,我们就可以通过数据线,把每一个的二进制数据传送到 MDR 当中。此时 CPU 会通过数据总线从 MDR 中取走一整个数据。

计算下总容量:三位的话就有 8 条线。

控制电路作用:①对于传输数据到 MAR 当中时可能并不稳定,所以控制电路做的一个工作就是,只有当 MAR 当中的数据稳定之后才会去打开译码器开关来进行读取并翻译地址来给出信号。②于此同时传输到 MDR 的数据也要稳定了之后才能够传输给数据总线,这也是由控制电路控制的。

自带有两个片选信号

  • CS:chip select,芯片选择信号
  • CE:chip enable,芯片使能信号

额外有两跟读 / 写控制线,由两种设计方案:①读写各单独一根。②读写一根线,根据输入的高低电平来确定是什么操作。

注意:通常题目中会告知你使用几根读 / 写线。

2.1.3、完整的存储器芯片以及封装图(认识片选线以及金属引脚作用)

完整的一个存储器芯片如下

此时对整块存储器芯片来进行封装

  • 驱动器主要用来放大信号的
  • 地址线用于接受外界传来的地址信息,CPU 通过地址总线传来的。
  • 数据线来进行数据的传输。
  • 片选线:来确定这块芯片是否可用。
  • 读写控制线:可能有一条,也有可能有两条。

片选线的作用

  • 一个内存条可能包含多块存储芯片,而有时候我们若是指定要读取某块芯片数据,那么我们可以针对那一块芯片数据传输低电压,其他存储芯片传输高电压,此时就能够单独对指定的存储芯片进行读取了。

** 对应每个存储芯片下都有如下图一样的金属引脚这是什么呢?** 这个是就是我们上图封装好之后对应的地址线、数据线、片选线以及读 / 写控制线相对应的引脚,用于其他模块来传入进来数据。

2.1.4、存储芯片寻址

关于寻址的问题主要来看存储器中的存储矩阵,数据是存储在这里:寻址方式可按照字节、字、半字、双字来进行寻址,不同寻址对应的编号也不同,若是更大是倍数,存储单元个数可进行右移

知识回顾

2.2、SRAM 与 DRAM

2.2.1、存储元件不同导致的特性差异

DRAM

在 2.1 节当中学习的就是 DRAM 芯片,采用的是电容存储的,对于 SRAM 则是采用的双稳态触发器来存储信息:

SRAM

双稳态触发器的读 / 写原理

其中双稳态触发器有 6 个,在这种存储器中可以呈现出两种稳定的状态:

  • 第一种稳态 A 是高电平,B 是低电平,此时对应着二进制 1。
  • 第二种稳态 A 是低电平,B 是高电平,此时对应着二进制 0。

对于左边电容存储元读出数据的数据线只有一根,右边双稳态触发器则需要两根来读取数据,我们可以根据 BL 或者 BLX 读出的是 0 或 1 就能够确定读出的是什么信号了。

如何写入数据呢?

  • 写入 0 时,给 BL 加低电平,BLX 加高电平。
  • 写入 1,左高右低。

2.2.2、DRAM 与 SRAM 的区别

两者的区别

一方面:存储元件上导致的区别,也就是读数据是否需要重写的情况,DRAM 在读数据后需要有一个重写操作,而 SRAM 无需重写。

另一方面

  • 制造成本:DRAM 只需要一个电容,SRAM 需要 6 个 MOS 管,可以看出 DRAM 成本更低,SRAM 成本高。
  • 集成度:DRAM 的电容很小,对比 SRAM 的小了很多,同样一块位置肯定是 DRAM 的电容数量更多,所以 DRAM 的集成度高,SRAM 集成度低。
  • 功耗:DRAM 对比 SRAM 所需的功耗更低,因为其元器件对比 SRAM 的少。

2.2.3、DRAM 与 SRAM 的刷新

2.2.3.1、了解刷新

对于 DRAM 需要 2ms 刷新一次,若是不刷新原本电容中的数据就会丢失!

2.2.3.2、刷新详细深入理解

针对于 DRAM 刷新来进行详细介绍

1、多久刷新一次?
  • 刷新周期:一般为 2ms。
2、每次刷新多少存储单元?介绍两种模型(含示例)
  • 以行为单位,每次刷新一行存储单元,但是对于每次刷新一行存储单元,这样的效率十分低,若是有 20 位,那么就需要 220,也就是百万个内存地址,试想若是一次刷新一行存储单元,那么需要刷新百万次,这个是十分耗时的,那么就要引入行列地址

简单模型:

行列地址模型:

将一个译码器分为两个也就是行列译码器,那么此时一个译码器负责 210,总共也只需要执行 210 次,此时只需要一千次,大大提升效率,分为拆为 n/2:

随着存储器发展,存储容量越来越大,现在一些存储器还有三维的排列,原理类似。

示例:给你一个地址 00000000 如何来进行访问。

第一种方案:选通的是 0 号存储单元

总共需要 28 也就是 256 根选通线:

第二种方案:各自拆成一般分别送到行地址译码器以及列地址译码器

针对于行列地址译码器只需要 32 根:

3、如何刷新?
  • 有硬件支持,读出一行的信息后重新写入,占用 1 个读 / 写周期。
4、在什么时刻刷新?(分散、集中、异步刷新)
  • 假设 DRAM 内部结构排列出 128x128 的形式,读 / 写周期(或称存取周期)0.5us【刷新一行的时间】。2ms 共 2ms/0.5us=4000 个周期。

有多种刷新思路如下:

①分散刷新:这种思路针在一个 2ms 周期中可以进行 2000 次刷新,是能够满足 128x128 中的 128 次的。

②集中刷新:集中一段时间进行读写,然后再集中一段时间去刷新,在这一段刷新时间中无法访问存储器

③异步刷新:在这个过程中将死时间进行了分散,可以利用 CPU 不需要访问存储器的时间段(例如利用 CPU 在译码的时间段)来进行刷新

2.2.4、送行列地址(DRAM 的优化,地址线复用技术)

同时送:一个地址前面部分送到行地址译码器,而地址后一半部分送到列地址译码器当中,此时需要同时传输行与列地址,也就是需要 n 位地址线来进行同时传输

在 DRAM 中通常采用地址线复用技术:也就是行地址与列地址通过前后两次分别进行传输,使用 n/2 根地址线,通过增加一个行地址缓冲器以及一个列地址缓冲器,分开传输

通过这种策略,原本 n 条地址线此时就可以优化为 n/2 根。

本节回顾

2.3、只读存储器 ROM

2.3.1、ROM 的发展史(MROM、PROM、EPROM、闪存、SSD)

ROM 的发展史如下: 基于上图的五个

①MROM:只能读而不能写的存储器。

初始化是厂家完成的,可根据需求来将指定数据写入,采用的是一种掩膜技术,对于掩膜技术只能够进行批量定制。

②为了提高只读存储器的灵活性,此时就发明了 PROM。用户可以使用专门的 PROM 写入器来写入信息,写一次后就无法更改。

③接着又出现了 EPROM,可以允许多次重写。可以通过一些特殊的手段往里面写数据。

针对于 EPROM 分为下面两个类型:

  • UVEPROM(uv 紫外线意思):可使用紫外线来照射擦除,注意是所有信息而不是部分信息。【灵活性不高】
  • EEPROM:可以采用电可擦除技术,擦除特定的字。【灵活性高】

④此时又出现了 Flash Memery(闪存),保留了 EEPROM 的优点断电后可以保存信息,还可进行多次的快速擦除重写。

注意点:闪存需要先擦除再写入,写速度比读速度更慢。

  • 位密度高解释:对于两块体积都相同的芯片来说,Flash Memery 存储元数量比 RAM 的要多,可以保存更多的位。

⑤接着随着技术发展,又出现 SSD(固态硬盘),也是由闪存芯片来存储二进制数据的,其中多了一个控制单元,用来控制多块闪存芯片的读和写。

实际上许多固态硬盘、U 盘的介质都是闪存芯片,与 U 盘的区别在于控制单元不一样。

2.3.2、认识 BIOS

CPU 在刚开始执行的一段程序,需要从 BIOS 中读取指令:

实际上对于主存同样包含 ROM,是由 RAM+ROM 组成,二者统一进行编址,如下:

本节回顾

三、主存储器与 CPU 的连接

3.1、单块存储芯片与 CPU 的连接

  • 字扩展:单个存储芯片是 8x8 位的,主存地址连接了 8 位,若是想要扩展主存字数可以采用该扩展。【可以连接多块存储芯片来扩展字数】
  • 位扩展:对于 8x8 的存储芯片,那么一个地址就只有 8 位,而现在的计算器一次可以处理 64 位数据,若是此时存储芯片字长 < 数据总线宽度,那么可以采用位扩展。【通过多块存储芯片的合理连接,可以让整个主存的存储字长扩展为与数据总线宽度一致】

以前的存储芯片中集成着 MDR 与 MAR,如今在计算机中这两个元件是集成在 CPU 当中:

  • CPU 中三个部件的作用:MDR 当中传输数据是通过数据总线;MAR 传输地址是通过地址总线传输数据的;CPU 还需要通过控制总线来发送一些控制信息来与主存进行一些读写操作。

目前主存中包含多块存储芯片见如下

3.2、存储器芯片的输入与输出信号元件介绍

  • 地址 (Address)、数据 (Data)、WE(write)、WR(read)

WE:表示写使能信号,write Enable,若是高电平表示写数据,低电平表示读数据。CPU 也有对应的 WE 线来进行发送信号,通过控制信号发送过去。

CS:片选信号,由于只有一块芯片工作,可以直接接上高电平信号,因为 CS 头上没有划横线,表示片选信号高电平有效。

来看整体的连接情况,可以发现数据总线仅仅只连接了一位,地址总线也只连接了一部分,并没有充分发挥 CPU 的性能,解决这样的问题可以给主存再加上一块相同型号的芯片

3.3、多块存储芯片与 CPU 的连接

3.3.1、位扩展

位扩展:此时我们总共有两块主存储器,总体来看数据读取位长有两位,此时可以同时读与同时写两位

新连接一块存储芯片,可以将新的 D0 连接到 CPU 的 D1,对应的 A 地址线与第一块连接一致即可读取时可以都传入到各自的地址线当中。

完成 8 位数据线扩展如下,我们需要增加 8 个 8K x 1 位的即可完成扩展:

3.3.2、字扩展(线选法与译码片选法,含字扩展示例)

主要包含两种选法

线选法:CPU 上的 n 根线对应 n 个存储芯片。

  • 举例:A0-A13 对应存储芯片的各个地址线,A14 对应存储芯片 A,A15 对应存储芯片 B。那么只有在 01xxxxx、10xxxxx 才能够分别表示一组存储芯片,那么对于 00、11 直接就浪费掉了(对于线选方式的 00 都不选、11 会造成数据线读取冲突,不允许有这类情况)

译码片选法:CPU 上的 n 根线对应 2n 个存储芯片,利用率更好。

  • 举例:A0-A13 对应存储芯片的各个地址线,对于一个线 + 一个译码器,那么就可以对应两个存储芯片,0 就是表示指定一个存储芯片可用,1 表示另一个存储芯片可用,比线选法利用率更高。

线选法

使用 CPU 的两个地址线来进行举例:

A13 与 A14 一个为 0,另一个为 1 时的最低地址与最高地址:分别各自表示

A13 与 A14 都是 1 则会造成冲突情况:可以看到底部出现了冲突

若是都是 0,由于 CS 表示的时高电平有效,此时两个存储芯片都不会选。

译码片选法

译码片选法:通过使用一个译码器来实现转换,1 个地址线可转 2 个,2 个地址线可转 4 个,也就是 2n

此时我们只使用一个 A13 来对应一个译码器,当 A13 为 1 时:通过译码器转换后,对于第一个存储芯片传输的为低电平那么第一个不选用,第二个存储芯片传输的则是 1 也就是高电平,此时第二个存储芯片生效

当 A13 为 0 时,此时第一个存储芯片生效:

地址范围为:

可以看到上面的 A13 仅仅只是选择一个转 2 个,那么对应这个译码器就是 1-2 译码器:可有 0xxxx、1xxxx 对应两个存储芯片

3-8 译码器:输入信号为 000、001、010、011、100、101、110、111,可接 8 个存储芯片

下面给出一个扩展 4 个存储芯片示例:在下面的存储芯片 CS 上有一个横线,表示低电平有效,此时你也可以看到对应的译码器上有一个圈表示是非的含义,也就是当这个线传输到 CS 横时为 0 才有效:

3.3.3、字位同时扩展

字位同时扩展示例:

CPU 是 64 位地址线,数据宽度为 8 位,对应的存储芯片是 16k x 4 位,那么此时我们需要 4 块存储芯片来进行字扩展,同时 2 个存储芯片需要进行位扩展,由于字位同时扩展,所以需要 2*4=8 块,可以看到上图的左边红框可以组成一个 16k x 8 位,那么需要 4 个来进行子扩展,则能够实现了主存容量扩展。

补充:译码器(包含介绍 CPU 译码器 存储芯片的过程、RAM 读周期详解)

可以看到下图的左右两边是两种不同的生效情况,左边是高电平有效、右边是低电平有效:

对应译码器中还包含使能信号:左边的是单个的,右边则有多个使能

介绍 CPU 译码器 存储芯片的过程:CPU 首先会通过地址线送出地址信号,包括更低的 13 位与更高的 3 位,地址信息是通过电信号来输出的,当 CPU 刚开始输出电信号的时候,电信号有可能不稳定,因此 CPU 送出这些地址信息之后,需要等一下,等电流稳定之后再发出主存请求信号(MREQ),也就是让选通线的一个信号有效,当一块存储芯片选通之后,这块存储芯片所接收到的信号一定是稳定的。

RAM 读周期详解

总结回顾

位扩展:使存储器的字长变得更长,从而更能发挥数据总线的传输能力。

字扩展:可以增加存储器的存储字数,可以更好的利用 CPU 的寻址能力。

可以在不同的维度扩展发挥数据总线的传输能力,增加存储器的存储字数更好的利用 CPU 的寻址能力。

四、提升主存读取速度双端口(双端口 RAM、多模块存储器策略)

4.1、理解存取周期,引出问题(含知识总览)

存取周期如下

对于 DRAM 芯片读请求是破坏性请求,读取之后需要进行恢复,上图中存取时间就是 DRAM 读取一个字的时间,读完之后则需要一段恢复时间,在这个恢复时间中 CPU 无法访问。

  • 对于 SRAM 恢复时间就会短很多。

此时针对于存储芯片读取一个字时需要等待恢复时间这种情况来提出问题并进行解决

1、多核 CPU 中一个 CPU 访问了一块内存之后需要恢复时间,那么由于是多核,此时另一个 CPU 在之前 CPU 的等待恢复时间也要访问该块空间,如何解决?

  • 解决方式:双口 RAM。

2、单核 CPU 读写速度比主存快很多,对于主存恢复时间过长如何解决?

  • 解决方式:多模块存储器。

4.2、双端口 RAM 解决问题 1:访问同一块存储空间,多个 CPU 如何解决等待恢复时间

双端口 RAM 如下进行设计

介绍:可以看到上图中的一个 RAM 左右两边都可以去联通 CPU,若是要支持这种多 CPU 的访问模式,我们需要在一个 RAM 存储器中有两组完全独立的数据线、地址线、控制线,于此同时 RAM 中也需要更多更复杂的控制电路。

好处:对于这种设计方式可以优化多核 CPU 访问一根内存条的速度。

多个端口对同一主存允许操作:不同端口对不同地址单元存取数据;不同端口对同一端口可读取数据;

  • 不允许的操作如:写写、读写。

解决不允许的操作方案:采用双端口时会出现四种情况,对于写写、读写操作应该禁止,这个禁止是通过电路来进行实现的。

4.3、多体并行存储器解决问题 2:单 CPU 多次访问主存等待恢复时间过长问题

4.3.1、认识高位以及低位交叉编址(了解区别与读取速度差异)

针对于单 CPU 多次访问主存等待恢复时间过长问题,我们可以采用多体并行存储器来进行解决,也就是将一块存储器来拆为多块可供 CPU 访问,可分为高位以及低位交叉编址

对于高位与低位交叉编址的区别是什么呢?每个地址是根据体号与体内地址组成,对于高位交叉编址是体号在前,体内地址在后;对于低位交叉编制是体内地址在前,体号在后。

对于不同的地址设计,对应的地址编号顺序也会受到影响各不相同,我们可以发现高位交叉编址的内存地址顺序依次是从第一根从上至下,接着第二个往下,而对于低位交叉编址则是一个一个地址分离对应的多块相隔,对于这样的区别有什么影响呢?

下面举一个例子:访问连续的 5 块地址,我们分别来看采用高位交叉编址与低位交叉编址的读取时间

①高位交叉编址

由于连续的 5 个地址都是在分为四根的第一根存储器中,那么相当于会连续访问 5 次同一根,每次访问的时间都包含了存取时间 1r 以及等待时间 3r:

可以看到每访问一次实际需要 4r,也就是 1T,第二次由于访问的也是同一根需要等待时间结束后才能够访问,之后的几次同样如此,总共需要时间为 5T。

②低位交叉编址

采用低位交叉编址地址编号是一根隔着一根的,所以访问第一位时是在第一根,此时需要使用读取时间 1r,在 1r 之后可以直接读取第二根,无需进行等待,后面 3、4 根同样如此,由于我们上面低位交叉编址是设置了 4 根,所以我们在第五次访问位的时候会访问第一根,此时可以发现,正好 3r 的等待时间已经结束,此时同样无需等待可直接进行访问。

采用这种方式可以十分高效速度去读取,耗时只需要 T + 4r,也就是 2T!

小总结:当访问一根内存条的存储器时,每次访问都必须有等待时间,对于同样顺序读地址时

  • 高位存储器:顺序读五个则是 5 * 5r= 25r 1T=5r,那么就是 5T
  • 低位存储器:顺序读五个 (访问的是不同存储单元) 则是 5 * 1r = 5r,而当读取第五个也就是第一块时,之前的等待时间刚好已经结束,可以再次进行读取,此时耗时为 1T+4r = 2T。| 微观层面时间开销的计算:T + (n - 1).r,宏观层面读写一个字的时间接近 r。

从效率上来看,低位比高位高出很多足足有 4 倍。

4.3.2、为什么要探讨 “连续” 访问的情况?

程序指令的执行是顺着一条一条往下执行的,一般就是连续存储,除非碰到 if else 情况。

4.3.3、低位交叉编址最佳需要采用多少个体呢?

上述可以看出低位交叉编址的多体存储器针对于连续地址访问效率十分高,那么具体应该取几个体呢

  • 应当保证模块数 m>=T/r(存取周期 T,存取时间 r),若是 m < T/r 时,那么当读取第 T 个时那么 T / r 个还在等待恢复中,无法进行读取此时就需要进行等待。

下面给出不同模块数的情况

总结表述:

4.3.4、思考:给定一个地址 x,如何确定它属于第几个存储体?

①直接根据末尾的体号来判断。②根据给定的 m,来让 x % m 进行取余处理。

4.3.5、多体并行存储器与单体多字存储器区别

前者可以任意去读取某个存储器中的字,后者每次只能去读取一行,有时候读取跨行的几个字会导致多读数据。

速度对比:前者每读取一个字接近 r,读取四个就是 4r;后者每次读取一行,读取一行需要 1T,也是 4r,所以读取速度差不多。

扩展介绍:双通道是什么?如何组合为双通道?

我们在日常生活中所说的扩容以及双通道实际上就是我们上述所介绍的高位交叉以及低位交叉情况,采用低位交叉可以构成双通道,此时读取速度可以大大提升!

如何构成双通道?一条 16GB 的可以换成两条 8GB 的,分别插入到上面相同颜色卡槽中,此时就可以构成双通道。

那么我们为什么要挑选相同主频以及相同容量的呢

  • 相同主频:若是购买主频不同的内存条,实际高主频的内存条就会出现降频的情况
  • 相同容量:若是容量不相等并且采用双通道的时候,相同容量的两个部分组成了低位交叉编址,在读取这一块内存的时候十分流畅,而对于多出来部分的内存条容量则是单通道,此时就会在游戏运行过程中有卡顿问题。

实战:对于电脑中的双通道我们也可以在系统里查看,例如下面的两条 8GB,分别在 0、2 号插槽,那么也就是出厂的时候就是配置的双通道。

本节回顾

五、外部存储器

5.1、磁盘存储器

5.1.1、认识磁盘存储器

计组:主要考察硬件特性;操作系统:考察对磁盘的管理,调度算法。

对于主机传来的 8bit 数据我们需要搞一个电路将其 8bit 数据搞成串行的方式 1bit、1bit 的进行写入,读取数据也同样如此。

磁盘读取二进制比特位的原理:磁带划过磁头下方时,磁头就可以 1bit、1bit 的往里面写数据,每次只能写 1bit;读数据同样如此,可以通过读线圈 1bit、1bit 的读数据。

特性:①磁盘每次读或写都是 1bit、1bit 进行操作的。②读与写操作是不能够一起进行的。

磁表面存储器的优缺点

认识磁盘存储器

5.1.2、磁盘存储器的组成

①存储区域

磁头:每个盘面都有一个读写磁头(一个磁盘存储器可能有多个盘面)。

磁道:每个盘面一圈一圈的就是磁道,由于磁盘内部有多个盘片,每个盘片划分多个磁道。

柱面:不同盘片相同编号位置磁道构成一个柱面。

扇区:每个盘面可以划分多个扇区

主机每次对磁盘读和写都是以扇区为单位。

②硬盘存储器

需要磁盘驱动器、磁盘控制器 (IO 控制器)、盘片

可以注意到:对于磁头有上下实际上可以读取上与下的盘片,最顶部与最底部没有。

5.1.3、磁盘的性能指标

①磁盘容量

容量:

  • 非格式化:物理层面上来看,可以存储的 bit 上限。
  • 格式化容量:磁盘一些扇区会损坏,防止一些扇区的损坏,导致磁盘无法正常工作,因此很多厂商生产的磁盘需要格式化,例如可以留下一些备用的扇区可以顶替使用,若是扇区 A 损坏就可以用扇区 B 来进行顶替。

格式化容量比非格式化容量要小。

②记录密度

  • 道密度:指定距离中有多少磁道。60 道 / cm
  • 位密度:单位磁道上能够记录的二进制代码尾数。600bit/cm
  • 面密度就是前两个乘积。

磁盘上扇区从外到里每一圈存储的 bit 位数都相同,只是密度不同,越靠内侧密度越低

③平均存取时间

寻道时间 + 旋转时间 + 传输时间 (让磁头划过整个区域完成读写)

  • 旋转磁盘时间若是题目没给,一般按照半圈来算

整个存取时间过程图示:

磁盘控制器延迟:给磁盘发出读写命令也需要花费一些时间。

④数据传输率

5.1.4、磁盘怎么确定要读取的扇区?认识磁盘地址

根据磁盘地址来进行编号:

  • 驱动器号就是我们系统中的对应磁盘
  • 柱面:磁头选中指定的圈圈位置,进行前后移动
  • 盘面号:之前图示可以看到磁头会有上下,所以的话需要进行选中某个磁头
  • 最后就是指定的扇区位置来进行互动。

5.1.5、磁盘的工作过程

磁盘的工作过程:寻址、读盘、写盘,都是通过控制字来进行发出的。

读取过程需要借助一个串 - 并变换电路:

5.1.6、认识磁盘阵列 RAID0-5(提升系统性能以及磁盘存储的可靠性)

磁盘阵列主要目的:提升系统性能以及磁盘存储的可靠性。

磁盘冗余阵列:将逻辑上相邻的数据实际放置在不同层面中,此时就能够进行并行的访问。

  • 同样也是采用分段的存储在不同字块上的思路。

RAID0:若是有一些扇区坏了的话无法恢复数据。没有容错能力。

可通过软件的处理,将原本逻辑盘连续的磁盘去管理为四个物理盘,此时可以使整个磁盘系统读写速度更快。

出现的问题:

  • 无冗余:没有多余空间存储备份一份数据,若是某个位出现错误,那么就会有永久性丢失。
  • 无校验:若是连续的位上有一位出现错误有问题,无法进行校验。

RAID1:镜像磁盘阵列

方案:可以采用更安全的磁盘阵列。每个物理磁盘上都存放一份数据,此时有冗余但有校验的功能,相对的代价则是存储空间浪费一半。1:1

RAID2:提高磁盘进一步利用率,逻辑上相邻的几个 bit 分散存储在四个物理磁盘中,同时增加几个磁盘用来保存 4bit 对应的 3bit 海明校验码就可以纠正一位错并恢复。4:3

RAID3-5:其他策略。越往后可靠性越高越安全。

为了增加可靠性与并行访问能力,商用级别经常使用这种磁盘冗余阵列提升磁盘系统性能与可靠性。

小总结如下

总结回顾

5.2、SSD 固态硬盘

2023 年出现选择题概率十分高。

5.2.1、机械硬盘 VS 固态硬盘

机械硬盘存储数据都是基于小盘面上的磁性物质来记录二进制 0 与 1;固态硬盘存储介质基于闪存技术 (u 盘同样也是)。

  • 在固态硬盘中一个个黑色块就是闪存芯片。

5.2.2、固态硬盘的组成

通过 IO 总线来发送逻辑地址,接着通过闪存翻译层来映射到对应的物理地址,闪存翻译层做的是地址变换的工作。

接着深挖闪存芯片内部的结构,一个闪存芯片由若干个数据块组成,一个块大小在 16KB-512KB。

每一个块可以拆解为一个个页,每个页大小为 512B-4KB。

注意:系统对于固态硬盘的读写是以页为单位的。每次读 / 写一个页。

  • 若是对于磁盘,那么一次读写就是对应一个块或者扇区。固态硬盘的一个页相当于磁盘的一个扇区。固态硬盘的一个块相当于一个磁道。而一个磁道包含多个扇区。

5.2.3、读 / 写特性

针对其中一个特性:固态硬盘会以块的单位擦除,擦干净的块,其中的每页都可以写一次,读无限次。

若是在一个块中先写了几个页,那么再去修改那几个页是不被允许的,除非去把整一块擦除才能够重新写。

若是我只想重写一页呢,难道要把整一块来进行擦除吗?实际上固态硬盘会将指定的除了那一页的其他页写入到其他块中也就是先复制到另一块中,然后将新的一页页写到另一块中,接着将原先的那一块擦除即可。

  • 相对于此时闪存翻译层会重新针对指定的逻辑快号映射新的物理地址也就是新的那块上。

由于这个特性导致固态硬盘读快,写慢

5.2.4、磨损均衡技术

关于机械硬盘与固态硬盘定位的区别:固态硬盘是通过电路迅速定位;机械硬盘则通过移动磁臂旋转。

  • 固态硬盘支持随机访问,访问任何一个地址都是同样时间。而若是对于机械硬盘的物理地址离磁臂比较远,则需要移动和旋转才行。

固态硬盘的缺点:若是频繁的在一个块上进行擦写重写,那么会导致坏掉。

根据这个缺点,就有了解决方案:磨损均衡技术。也就是想办法将擦除平均的分布在各个块上,用于提升使用寿命。针对于读多写少的数据块则可以将其数据迁移到比较老的块上。主要原因是读多写少,那么对于擦除的需求就很少。

  • 会在后台监控每个块读 / 写多少次,根据实际的需求来进行适当迁移。

扩展:固态硬盘的寿命

五、高速缓冲存储器

大题和小题的高频考点

5.1、Cache 的基本概念和原理

5.1.1、存储系统存在的问题

存储系统存在的问题:优化后速度与 CPU 差距依旧很大,可以增加一个 cache 层来进行缓和。

5.1.2、Cache 的工作原理

cache 的工作原理:在一小段时间内,会有同样的一段代码或者数据被频繁的访问与使用,此时我们可以将其读入到 cache 中。

  • 目前 cache 是直接集成到 CPU 内部的,并且使用 SRAM 实现。由于 SRAM 集成度低,所以也导致了容量有限。

5.1.3、程序的局部性原理

空间局部性 (与目前使用比较靠近的)、时间局部性 (最近未来要使用的,很可能是现在要使用的)

  • 程序的局部性原理:使用程序 A 来进行举例。

举例:例如访问二维数组,若是跳着去访问隔行的空间局部性更差,若是依次是一行中的元素,那么空间局部性更好。

5.1.4、性能分析(平均访问时间计算)

性能分析:H 表示 CPU 访问信息在 cache 的比率,1-H 表示未命中率

平均访问时间

  • 方案 1:首先会去找 Cache 中的,接着会去找主存中的数据。t = Htc + (1 - H)(tc+tm)
  • 方案 2:在找 Cache 的同时去找主存中的数据,此时 t=Htc + (1 - H)tm

实际例题

5.1.5、空间局部性原理,如何界定 “周围”

由于主存与 Cache 以 “块” 为单位进行数据交换,而对于数组a[0][1]我们可以根据地址信息来判断其在哪一个块中,我们可以将这一块的所有信息放入到 cache 中。

  • cache 与主存中都是以块作为单位的,此时对于 cache 与主存之间进行数据交换就能够十分方便了。
  • 主存的一个块也被称为一个页 / 页面 / 页框。Cache 中的块也称为行。

此时主存的地址可以分为块号、块内地址。

知识点回顾

下面是接下来章节要学习并解决的问题:

  • cache 与主存数据块对应关系:cache 与主存的映射方式。
  • cache 很小,主存很大,若是 cache 满了如何解决?采用替换算法。
  • cache 修改了 cache 中的数据副本,如何确保主存中数据母本的一致性。

5.2、Cache 与主存的映射算法(三种)

三种映射方式以及认识 Cache 标记号与有效位

三种映射方式:全相联映射、直接映射、组相联映射

  • 全相联映射:主存块可以放在 Cache 的任意位置。
  • 直接映射:每个主存块只能放到一个特定的位置。
  • 组相联映射:每个主存块可放到特定分组的任意一个位置。确定分组后,选择空闲的位置存放。

如何区分 Cache 中存放的是哪个主存块

  • 给每个 Cache 增加一个 “标记”,记录对应的主存块号。若是没有存储主存数据的 cache 块就是用 0 作为标记。

此时标记号为 0 也是有一个问题,那就是主存地址是从 0 开始的,那么此时就会产生冲突!如何解决呢?

  • 设置一个有效位:1 表示有存储,0 表示无存储。

5.2.1、全相联映射(随意放)

①主存块号与块内地址分布?

给定主存地址总空间 256MB,行长为 64B

256MB=228B,计算主存块号数即为 228B / 26B = 222,即主存块号为 22,块内地址为 6。

②如何进行划分?

放主存中的第一块时,可以放入到 cache 中的任意一个块中。放入好之后会记录标记号 (主存地址) 以及有效位为 1(表示已占位置)

③如何访问主存地址呢?

1、首先会使用主存数据的前 22 个在 cache 中标记进行匹配对比,若是比对相同,若是有效位为 1,即表示 cache 命中。

2、若是不能够命中,根据有效位 = 0 情况,表示是否可访问,若是为 0 则直接到主存中去找数据。

5.2.2、直接映射(只能放固定位置)

主存映射 cache 位置公式:主存块在cache中的位置 = 主存块号 % Cache总块数

存放流程:若是 cache 有 0-7 块,主存有 0-222-1,按照规则来看,我们依次来放 0、7 两个主存块:

  • 首先放置主存 0 块,0 % 7 = 0,此时 cache 块空闲,直接将主存数据放入到 cache 的 0 块中。
  • 接着放置主存 7 块,7 % 7 = 0,此时 cache 已被占用,此时同样会进行放入操作,直接覆盖掉之前的主存 0 块数据。

通过上面流程可以很明显发现一个问题:就是在分配主存的某一个块时,对应的 cache 位置被占用,而此时又有其他位置空闲,但是这个主存块就是非一个块不可,若是先前被人写了还是会直接上去覆盖掉!

缺点:其他地方有空闲 Cache 块,但是 7 号主存块不能够使用,空间利用率不充分。

关于标记存储内容的优化

引出:例如主存的前 22 个块号是 0…01000,通过 % 7 此时确定 cache 的位置为 0,此时在 cache 中标记位即同样为主存的前 22 个块号 0…01000,此时我们可以对这个标记位进行优化。

优化点:我们可以看到我们是 %cache 的块数,那么最终前 22 块号的最后 3 位就是我们的 cache 编号,此时我们可以省略前 22 个中最后的 3 位 (也就是 cache 的块数二进制位数),可以优化为 0…01,此时即可完成对应主存位置的标记,此时就只需要 19 位即可。

块内地址分布

以之前全相联映射的案例为主。

主存块号分为:19 位标记 + 3 位行号,块内地址为 6 块。

直接映射访存流程

①根据主存块号的后 3 位来确定 cache 行。

②若主存块号的前 19 位与 Cache 标记匹配且有效位 = 1,则 Cache 命中,访问 001110 的单元。

②若是未命中或有效位 = 0,则正常访问主存。

5.2.3、组相联映射(可放到特定分组)

确定主存数据在 cache 位置公式所属分组 = 主存块号 % 分组数

  • 块内地址分布:2 路组相联映射(2 块为一组,分四组),n 路就是 n 块为一组。

主存块号分为:20 位标记 + 2 位组号,块内地址为 6 块。

标记位置优化点:由于分组数为 4 位,可用两位表示,此时我们可以省略在标号中的末尾两位去表示主存的位置。此时标记位只需要存储 20 位即可。

组相联映射访存流程

①根据主存块号后 2 位确定所属分组号。

②若是前 20 位与分组内的某个标号匹配且有效位为 1,此时 cache 命中。

③若是未命中,则直接访问主存。

知识点回顾

5.3、Cache 替换算法(解决 Cache 满的问题)

5.3.1、针对三种映射方式是否使用替换算法讨论

全相联映射:只有 Cache 全部满了之后,才需要进行替换。

  • 实现简单,没有考虑到局部性原理,命中率低,实际效果不稳定。

直接映射:无需考虑替换算法,可直接进行替换。

组相联映射:只有指定分组满了才需要进行替换,需要在分组内选择替换哪一块。

总结:全相联、组相联映射需要替换算法。

5.3.2、四种替换算法

5.3.2.1、随机算法

随机算法:若是 cache 已满,随机选择一块替换。

5.3.2.2、先进先出算法

先进先出算法:若是 cache 已满,则替换最先被调入 cache 中的块。

  • 实现简单,最开始按照 0、1、2、3 放入 cache,接着轮流替换 0、1、2、3。该算法没有考虑到局部性原理,最先被调用的 cache 块可能是被频繁访问的。
  • 抖动现象:频繁的换入换出现象。
5.3.2.3、近期最少使用算法(LRU)

近期最少使用算法(LRU):每一个 cache 块设置计数器,用于记录该 cache 多久没有被访问了。若是 cache 满,那么替换计数器中最大的。

  • 当访问一个 cache 块没有时,从该 cache 块向前看分别访问了哪几个,找最晚被访问过的来进行替换。

流程

  1. 命中时,所命中的行计数器清零,比其低的计数器加 1,其余不变。
  2. 未命中且还有空闲行时,新装入的行的计数器置 0,其余非空闲行的计数器置 0,其余非空闲行全 + 1。
  3. 未命中且无空闲行时,计数值最大的行的信息块被淘汰,新装入的块计数器置 0,其余全加 1。、

计数器优化点:cache 块的总数 = 2n,则计算器只需 n 位,且 Cache 装满后所有计数器的值一定不重复。

效果:LRU 算法是基于局部性原理的,合理的,实际应用效果优秀。

发生抖动情况:若被频繁访问的主存块数量 > Cache 行的数量,则会发生抖动。

5.3.2.4、最近不经常使用算法(LFU)

最近不经常使用算法(LFU):每一个 cache 块也有计数器,用于记录每个 cache 块被访问过几次,当 Cache 满后替换 “计数器” 最小的。

计数规则:新调入的块计数器 = 0,之后每被访问一次计数器 + 1,需要替换时,选择计数器最小的一行。

  • 若是有多个计数器最小的行,可按行号递增或 FIFO 策略进行选择:例如优先选择最上面的行号 (最小的行号)。或者按照先进先出的规则

问题:曾经被经常访问的主存块在未来不一定用得到(例如:微信视频聊天相关的块),并没有遵循局部性原理,实际运用效果不如 LRU。

  • 举例:若是一段时间频繁使用一段代码,这个代码对应的计数器累加到十分高,而后期使用的特别少,由于该计数器特别高,此时就会长时间的贮存在 cache 中,而不会替换掉。

知识点总结

5.4、cache 写策略(修改 cache 中数据副本,确保主存中数据母本的一致性)

根据 cache 是否命中来进行不同的处理。

写命中:全写法、写回法。

写不命中:写分配法、非写分配法。

为什么不讨论读命中、读不命中的情况?

  • 读操作不会导致 Cache 和主存的数据不一致。

5.4.1、写命中

5.4.1.1、写回法

写回法:当 CPU 对 Cache 写命中时,只修改 Cache 中的内容,而不立即写入主存,只有当此块被换出时才写回主存。

注意:对于指定 cache 块是否被修改过,我们可以使用一位脏位来表示其状态,1 表示修改过,0 表示没有被修改过。

好处与坏处:可以减少访存次数,但存在数据不一致的隐患。

5.4.1.2、全写法 (或写直通法)

全写法 (或写直通法):当 CPU 对 Cache 写命中时,必须将数据同时写入到 Cache 和主存,一般使用写缓存。

好坏处:访存次数增加,速度变慢,但更能保证数据的一致性。

写缓冲:使用 SRAM 实现的 FIFO 队列 (先进先出),写缓冲比较快。

详细过程:若是 CPU 命中 cache 中 #2 时,先会往 cache 指定块 #2 中写入,接着会向写缓冲中写入数据 A,此时又命中了 cache 中的 #1,同样会先写入到 cache 中的 #1,接着向写缓冲中写入 B。此时队列中顺序为 AB,每次两步写完之后 CPU 就去干其他事情了,此时对于写缓冲中的数据则由专门的控制电路控制下逐一写回。

  • 由于写缓冲是由 SRAM 实现,CPU 直接写入到 SRAM 中比写入到主存中快得多。

好处坏处:使用写缓冲后,CPU 写的速度很快,若是写操作不频繁,则效果很好;若是写操作很频繁,可能会因为写缓冲饱和而发生阻塞。

5.4.2、写不命中

5.4.2.1、写分配法

写分配法:当 CPU 对 Cache 写不命中时,把主存中的块调入 cache,在 cache 中修改。通常搭配写回法使用。

5.4.2.2、非写分配法

非写分配法:当 CPU 对 Cache 写不命中时只写入主存,不调入 Cache,搭配全写法。

注意:只有读操作未命中 cache 时,才会将主存的这块地址调入 cache。

5.4.3、多级 cache

最接近 CPU 的为 L1,包含有 Write Buffer。

举例:目前有 L1、L2 两级 Cache,L2 中保存的是主存中的一小部分数据,而 L1 中保存的则是 L2 中的一小部分数据。

对于各级 cache 中同样也需要保持数据的一致性,各级之间需要采用 “全写法”+ 非写分配法来保持。

六、虚拟存储器

6.1、页式存储器

6.1.1、认识页式存储(引出逻辑地址、物理地址、页表)

cache 与主存之间传输以块为单位。

页式存储:一个程序 (进程) 在逻辑上被分为若干个大小相等的 “页面”,页的大小实际上是与我们主存块的大小是相同的,我们可以将一个 4KB 的程序分为 4 个页,可以将 4 个页离散的放入到主存中各个不同的位置。

  • 不会直接将整个序的代码数据连续的放入到内存中。

  • 页号(Page Number)指示要访问哪个虚拟页面,偏移量(Page Offset)则指示要访问页面内的哪个字节。(详细来说:页表中的页内地址存储的是虚拟页面内部的偏移量,CPU 会将该偏移量与页表项中的物理页面的起始地址相加,从而计算出物理地址。)

若是一个程序被拆分为多块后离散存储到主存中,如何执行?引入逻辑地址、物理地址概念。

逻辑地址:程序员看到的视角,逻辑地址分为逻辑页号 + 页内地址,逻辑页号指的是对应程序分页的页号。此时我们可以将对应的逻辑页号去映射主存中的主存块号(逻辑地址映射物理地址),最终将物理地址 + 页内地址来进行拼接即可。

  • 对于这种映射关系我们去存储在页表中,在页表中包含逻辑页号以及主存块号。

页表:数据存储在主存当中,CPU 在进行地址转换的时候需要去查询页表,意味着 CPU 需要进行一次访存操作。页表中的一行表示为页表项,一个页表项对应着逻辑页号以及主存块号。

6.1.2、地址变换过程(慢表、快表)

基于慢表的地址变换过程

地址变换过程:页表基址寄存器中存储了页表在主存中的地址

查询主存中的页表 (慢表) 流程

①首先给出操作码和执行地址(000001 001000000011),拆分得到其中的逻辑地址(001000000011),逻辑地址 = 逻辑页号 + 页内地址(001000000011 = 00 + 1000000011)。

②查询主存中的页表,根据其中的逻辑页号来去匹配得到主存的物理地址 00 000000000010,将物理地址与页内地址拼接 = 000000000010 1000000011,即可得到物理地址。【查询页表一次访存】

③得到物理地址后我们会再先去 cache 中去进行查询。

基于快表的地址变换过程

上面写出的地址变换过程可以发现其中去页表里查询 00 这个逻辑页号时会去主存中找到这一块数据,那么若是之后访问该逻辑地址同样都是 00,那么此时就不太高效,如何解决呢?

基于这个问题,我们来引入快表 (TLB),再此之前我们存储到主存中的页表在这里可以称为慢表。引入快表之后,整个过程如何?

快表:存放在高速缓冲存储器中,同样包含标记、主存块号两个部分,一开始快表是空的

查询快表流程

①在 cache 中查询快表指定的逻辑页号,若是有,直接获取到。【访问 cache1 次】

②若是没有,那么此时执行查询主存中的页表 (慢表) 的流程。【访存 1 次】

③查询得到逻辑页号 + 主存块号后即可存入到快表,可供之后再次使用。

6.1.3、快表与 cache,快表与慢表区别

注意快表与 cache 区别:

  1. 快表中存储的是页表项的副本,Cache 中存储的是主存块的副本。
  2. 快表是在地址变换的时候起到加速的作用,cache 是在最终得到的地址 (物理地址) 然后访问这个地址的时候起到加速的作用。

快表、慢表区别:

  1. 快表采用 SRAM;慢表采用 DRAM。
  2. 电路方面,快表采用 “相联存储器”,可以按照内容寻址。

快表作用:加快地址变换的速度,减少一次访存。

知识回顾

6.2、虚拟存储器

虚拟存储系统:用户感觉到使用的容量比真实使用的物理容量要大。

例如:微信有 1GB 的数据,那么实际加载到内存中仅仅只是一部分,我们如何去界定这么一部分的数据呢?

6.2.1、页式虚拟存储器(含存储器的层次化结构)

  • 主存块号、快存块号。
  • 有效位:表示对应的数据是否被调入主存,若是已经调入了则为 1,并且物理页或磁盘地址指向了主存。
  • 访问位:主要用于页面替换算法,主要当对应的页表填满了之后需要进行替换才增加的一位。可以记录每个页面实际的访问次数,通过实际的访问次数可以实现相应的 LFU(页面替换算法主要解决的是主存与辅存之间的替换)
  • 脏位:若是我们对主存块号中的内容进行修改后,此时我们之后需要将其写回主存,所以我们需要设置一个脏位。

存储器的层次化结构

主存 - 辅存:主要由操作系统完成。

Cache - 主存:主要由硬件自动完成。

6.2.2、段式虚拟存储器

页式、段式存储器的比对

段式存储器:按照功能模块拆分,每一段大小不一样。

虚拟地址结构:段号 + 段内地址

段表:在原先基础上增加段长,包含段首址、装入位、段长。

  • 段首址(Base Address):指逻辑段在物理内存中的起始地址。段首址与段号(Segment Number)一起共同确定逻辑地址的实际物理地址。
  • 装入位([Virtual] Memory Bound): 是指在逻辑段和逻辑上限之间的一段连续的虚拟地址,并表示逻辑段在内存中的大小,即它所占用的虚拟地址空间的大小。它的计算方式为逻辑首址加上段长减一(在某些系统中也称为段界限)。
  • 段长(Length):一个逻辑段在物理内存中所占的长度,即逻辑段中最后一个单元的地址减去逻辑段的起始地址。段长和装入地址一起确定了逻辑段的虚拟地址范围。

6.2.3、段页式虚拟存储器

段页式虚拟存储器:先将一个程序分段,再进行分页。也就是首先按照功能模块分段,接着将每个容量不相同的段进行分页(每页容量一致)。

段页式虚拟存储将程序内存空间分为多个逻辑段,每个逻辑段又被进一步分为多个大小固定的页。
程序访问内存时,首先生成虚地址,它被分成了两个部分:段号和页号。每个部分都表示了不同的含义。

具体来说,虚地址被分解为以下两部分:

  1. 段号(Segment Number):指明所访问的是哪个逻辑段,由段表中的段号进行解释,确定了要访问哪个逻辑段。
  2. 页号及页内偏移量(Page Number and Offset):指明要访问所选定逻辑段中的哪个页以及访问该页中的哪个单元(字节),其中页号与页表相关联,指向所要求的页表项,而页内偏移量则确定了所要访问的特定单元(字节)所在的地址偏移量。

然后,操作系统将逻辑地址转换为物理地址。在分段分页的虚拟存储管理系统中,逻辑地址中的段号和页号将被用于从段表和页表中检索对应的物理地址。最终,通过物理地址来访问实际位于物理内存中的数据。