存储技术
存储器系统
实际上,存储器系统(memory system) 是一个具有不同容量、成本和访问时间的存储设备的层次结构。CPU 寄存器保存着最常用的数据。靠近 CPU 的小的、快速的高速缓存存储器(cache memory))作为一部分存储在相对慢速的主存储器(main memory))中数据和指令的缓冲区域。主存缓存存储在容量较大的、慢速磁盘上的数据,而这些磁盘常常又作为存储在通过网络连接的其他机器的磁盘或磁带上的数据的缓冲区域。
存储器层次结构是可行的,这是因为与下一个更低层次的存储设备相比来说,一个编写良好的程序倾向千更频繁地访问某一个层次上的存储设备。所以,下一层的存储设备可以更慢速一点,也因此可以更大,每个比特位更便宜。整体效果是一个大的存储器池,其成本与层次结构底层最便宜的存储设备相当,但是却以接近于层次结构顶部存储设备的高速率向程序提供数据。
随机访问存储器
随机访问存储器分为两种:静态的和动态的。
静态RAM(SRAM) 比 动态RAM(DRAM) 更快,但也贵得多。SRAM 用来作为高速缓存存储器,既可以在CPU 芯片上,也可以在片下。DRAM 用来作为主存以及图形系统的帧缓冲区。典型地,一个桌面系统的 SRAM 不会超过几兆字节,但是 DRAM 却有几百或几千兆字节。
只要有供电, SRAM 就会保持不变。与 DRAM 不同,它不需要刷新。SRAM 的存取比 DRAM 快。SRAM 对诸如光和电噪声这样的干扰不敏感。代价是 SRAM 单元比 DRAM 单元使用更多的晶体管,因而密集度低,而且更贵,功耗更大。
静态 RAM
SRAM 将每个位存储在一个双稳态的存储器单元里。每个单元是用一个六晶体管电路来实现的。
这个电路有这样一个属性,它可以无限期地保持在两个不同的电压配置或状态之一,其他任何状态都是不稳定的。
当钟摆倾斜到最左边或最右边时,它是稳定的。从其他任何位置,钟摆都会倒向一边或另一边。原则上,钟摆也能在垂直的位置尤限期地保持平衡,但是这个状态是亚稳态的(metastable)最细微的扰动也能使它倒下,而且一旦倒下就永远不会再恢复到垂直的位置。
由千 SRAM 存储器单元的双稳态特性,只要有电,它就会永远地保持它的值。即使有干扰(例如电子噪音)来扰乱电压,当干扰消除时,电路就会恢复到稳定值。
动态 RAM
DRAM 存储器可以制造得非常密集--每个单元由一个电容和一个访问品体管组成。但是,与 SRAM 不同,DRAM 存储器单元对干扰非常敏感。当电容的电压被扰乱之后,它就永远不会恢复了。暴露在光线下会导致电容电压改变。
很多原因会导致漏电,使得 DRAM 单元在 10~100 毫秒时间内失去电荷,那么保存的内容也就丢失了。内存系统必须周期性地通过读出,然后重写来刷新内存每一位。
易失性存储器
如果断电, DRAM 和 SRAM 会丢失它们的信息,从这个意义上说,它们是易失的(volatile) 。
- 对于 SRAM,虽然它是基于双稳态触发器电路存储数据,速度快且只要电源不断数据就一直保存。但是一旦断电,双稳态触发器失去电源支持,无法维持原有的状态,存储的数据就会丢失。
- DRAM 存储单元是基于电容的,数据以电荷形式存储在电容中。电容会自然漏电,在正常工作时通过定期刷新来保持数据。当断电时,没有了刷新电路的工作,电容中的电荷会很快流失,导致数据丢失。
非易失性存储器
非易失性存储器(nonvolatile memory) 即使是在关电后,仍然保存着它们的信息。
常见的非易失性存储器有只读存储器(ROM)、闪存(Flash Memory)等。例如,ROM 在制造时就将数据固化在芯片中,其存储的数据不会因为断电而丢失,它通常用于存储计算机的基本输入输出系统(BIOS)等重要的、不需要修改的程序和数据。闪存则是通过浮栅晶体管来存储电荷,并且可以在断电后长时间保存数据,它被广泛应用于 U 盘、固态硬盘(SSD)等存储设备。
访问主存(随机访问存储器)
数据流通过称为总线(bus) 的共享电子电路在处理器和DRAM 主存之间来来回回。每次CPU 和主存之间的数据传送都是通过一系列步骤来完成的,这些步骤称为总线事务。读事务从主存传送数据到CPU 。写事务从CPU 传送数据到主存。
读事务:movq A,%rax
- 首先, CPU 将地址 A 放到系统总线上。I/O 桥将信号传递到内存总线
- 接下来,主存感觉到内存总线上的地址信号,从内存总线读地址,从 DRAM 取出数据字,并将数据写到内存总线。I/O 桥将内存总线信号翻译成系统总线信号,然后沿着系统总线传递
- 最后, CPU 感觉到系统总线上的数据,从总线上读数据,并将数据复制到寄存器 %rax
写事务:movq %rax,A
- 首先,CPU 将地址放到系统总线上。内存从内存总线读出地址,并等待数据到达
- 接下来, CPU 将 %rax 中的数据字复制到系统总线
- 最后,主存从内存总线读出数据字,并且将这些位存储到 DRAM 中
磁盘存储之访问磁盘
CPU 使用一种称为 内存映射 I/O 的技术来向 I/O 设备发射命令。在使用内存映射 I/O 的系统中,地址空间中有一块地址是为与 I/O 设备通信保留的。每个这样的地址称为一个 I/O 端口。当一个设备连接到总线时,它与一个或多个端口相关联(或它被映射到一个或多个端口)。
来看一个简单的例子,假设磁盘控制器映射到端口 0xa0 。随后, CPU 可能通过执行三个对地址 0xa0 的存储指令发起磁盘读:
- 第一条指令是发送一个命令字,告诉磁盘发起一个读,同时还发送了其他的参数,例如当读完成时,是否中断CPU。
- 第二条指令指明应该读的逻辑块号。
- 第三条指令指明应该存储磁盘扇区内容的主存地址。
在磁盘控制器收到来自 CPU 的读命令之后,它将逻辑块号翻译成一个扇区地址,读该扇区的内容,然后将这些内容直接传送到主存,不需要CPU 的干涉。设备可以自己执行读或者写总线事务而不需要CPU 干涉的过程,称为直接内存访问(Direct Memory Access,DMA)。这种数据传送称为DMA 传送(DMA transfer) 。
在 DMA 传送完成,磁盘扇区的内容被安全地存储在主存中以后,磁盘控制器通过给 CPU 发送一个中断信号来通知 CPU。基本思想是中断会发信号到 CPU 芯片的一个外部引脚上。这会导致 CPU 暂停它当前正在做的工作,跳转到一个操作系统例程。这个程序会记录下 I/O 已经完成,然后将控制返回到 CPU 被中断的地方。
固态硬盘(SSD)
固态硬盘(Solid State Disk , SSD) 是一种基于闪存的存储技术,在某些情况下是传统旋转磁盘的极有吸引力的替代产品。
读 SSD 比写要快。随机读和写的性能差别是由底层闪存基本属性决定的。
如上图所示,一个闪存由 B 个块的序列组成,每个块由 P 页组成。通常,页的大小是 512 字节 ~ 4KB, 块是由 32 ~ 128 页组成的,块的大小为 16KB ~ 512KB 。
数据是以页为单位读写的。只有在一页所属的块整个被擦除之后,才能写这一页(通常是指该块中的所有位都被设置为1) 。不过,一旦一个块被擦除了,块中每一个页都可以不需要再进行擦除就写一次。在大约进行 100 000 次重复写之后,块就会磨损坏。一旦一个块磨损坏之后,就不能再使用了。
随机写很慢,有两个原因。首先,擦除块需要相对较长的时间, 1ms 级的,比访问页所需时间要高一个数量级。其次,如果写操作试图修改一个包含巳经有数据(也就是不是全为1) 的页 p, 那么这个块中所有带有用数据的页都必须被复制到一个新(擦除过的)块,然后才能进行对页 p 的写。
局部性
局部性通常有两种不同的形式:时间局部性和空间局部性
- 在一个具有良好时间局部性的程序中,被引用过一次的内存位置很可能在不远的将来再被多次引用。
- 在一个具有良好空间局部性的程序中,如果一个内存位置被引用了一次,那么程序很可能在不远的将来引用附近的一个内存位置。
现代计算机系统的各个层次,从硬件到操作系统、再到应用程序,它们的设计都利用了局部性。在硬件层,局部性原理允许计算机设计者通过引入称为高速缓存存储器的小而快速的存储器来保存最近被引用的指令和数据项,从而提高对主存的访问速度。在操作系统级,局部性原理允许系统使用主存作为虚拟地址空间最近被引用块的高速缓存。类似地,操作系统用主存来缓存磁盘文件系统中最近被使用的磁盘块。局部性原理在应用程序的设计中也扮演着重要的角色。例如, Web 浏览器将最近被引用的文档放在本地磁盘上,利用的就是时间局部性。大容最的Web 服务器将最近被请求的文档放在前端磁盘高速缓存中,这些缓存能满足对这些文档的请求,而不需要服务器的任何干预。
存储器层次结构中的缓存
下图展示了一个典型的存储器层次结构。一般而言,从高层往底层走,存储设备变得更慢、更便宜和更大。在最高层(L0 ), 是少量快速的 CPU 寄存器, CPU 可以在一个时钟周期内访问它们。
存储器层次结构的中心思想是,对于每个 k,位于 k 层的更快更小的存储设备作为位于 k + 1 层的更大更慢的存储设备的缓存。换句话说,层次结构中的每一层都缓存来自较低一层的数据对象。例如,本地磁盘作为通过网络从远程磁盘取出的文件(例如Web 页面)的缓存,主存作为本地磁盘上数据的缓存,依此类推,直到最小的缓存 CPU 寄存器组。
第 k 层的存储器被划分成较少的块的集合,每个块的大小与 k + 1 层的块的大小一样。在任何时刻,第k 层的缓存包含第k+l 层块的一个子集的副本。
如上图所示,k 层中的 4、9、14、3 就是 k + 1 层的一部分元素,即 k 层 就是 k + 1层的缓存。
数据总是以块大小为传送单元在第 k 层和第 k + 1 层之间来回复制的。虽然在层次结构中任何一对相邻的层次之间块大小是固定的,但是其他的层次对之间可以有不同的块大小。
一个真实的高速缓存层次结构的解剖
到目前为止,我们一直假设高速缓存只保存程序数据。不过,实际上,高速缓存既保存数据,也保存指令。只保存指令的高速缓存称为 i-cache 。只保存程序数据的高速缓存称为 d-cache 。既保存指令又包括数据的高速缓存称为统一的高速缓存。
现代处理器包括独立的 i-cache 和 d-cache 。这样做有很多原因。有两个独立的高速缓存,处理器能够同时读一个指令字和一个数据字。i-cache 通常是只读的,因此比较简单。通常会针对不同的访问模式来优化这两个高速缓存,它们可以有不同的块大小,相联度和容量。使用不同的高速缓存也确保了数据访问不会与指令访问形成冲突不命中,反过来也是一样,代价就是可能会引起容量不命中增加。
⭐️内容取自《深入理解计算机系统》,仅从中取出个人以为需要纪录的内容。不追求内容的完整性,却也不会丢失所记内容的逻辑性。如果需要了解细致,建议读原书