2.3 存储器结构
计算机程序必须在主存储器(也称之为随机读写存储器或简称RAM)中才可以被执行。主存储器是唯一能够被处理器直接访问的大块存储空间(容量在数百万到数十亿字节之间)。它是一种半导体存储器,被称为动态随机读写存储器(DRAM),它由存储器字队列组成。每个字都有它自己的地址。通过调用load或store指令来对具体的地址进行读写。load指令一次将一个字从主存储器移动到CPU的某个内部寄存器中;store指令则将寄存器内容转移到主存储器中。除了直接调用load和store指令以外,CPU自动的从主存储器中读取指令执行。
在采用冯诺伊曼体系结构的计算机系统中,一个典型的指令周期首先从内存中读取指令,然后将指令存储到指令寄存器中。该指令将被解码,也可能需要从内存中读取操作数并将操作数存储到一些内部寄存器中。要注意到,内存单元仅仅被视为内存地址流;并不知道内存地址是如何产生的(来自指令计数器、变址寻址、间接寻址、线性地址等等)或者它们是什么(指令还是数据)的地址。因此,我们可以忽视内存地址是怎样产生的。我们仅仅知道内存地址序列由正在运行的程序产生。
理想的,我们希望能够将程序和数据长久的保存在主存储器中。但实际上这是不可能的,主要有如下两个原因:
1. 主存储器通常太小而不能长久的存放所有需要的程序和数据。
2. 主存储器是一种易失性的存储设备,会在掉电时丢失存储的信息,某些其它的原因也会造成数据的丢失。
这样,大多数计算机提供了辅助存储器作为对主存储器的一个扩充。辅助存储器主要用来长久的保存大量数据。
磁盘是应用最常用的辅助存储器,它可以保存程序和数据。大多数程序(网页浏览器、编译器、文字处理软件、电子制表软件等)在载入内存前存储在磁盘上。有些程序利用磁盘存放原始数据和运算结果。因此,合适的磁盘管理程序对一个计算机系统来说是相当重要的,这个问题将在第14章中讨论。
从更大的方面讲,前面提到的寄存器、主存储器和磁盘可能仅仅是许多存储系统的一部分。另外还有高速缓冲存储器、CD-ROM、磁带等。每个存储系统都提供了基本的数据存储能力,并且能够保持数据不会丢失。各种各样的存储系统之间的主要不同点在于速度、价格、尺寸和易失性。我们将在2.3.1节到2.3.3节讨论主存储器、磁盘和磁带,因为它们具备了所有重要的具备商用价值的存储设备的一般特性。将在第14章中讨论软盘驱动器、硬盘驱动器、CD-ROM和DVD等设备的具体特性。
2.3.1 主存储器
主存储器和处理器内部寄存器是唯一能够由CPU直接访问的存储器。有些机器指令将内存地址作为参数,但是却没有指令将磁盘地址作为参数。所以,指令运行时所需要的数据必须要存储在这些能够直接访问的存储设备中。如果数据不在内存中,那么CPU首先把它们转移到内存中,然后才能够对它们进行操作。
在I/O操作的情况下(就像2.1节提到的那样),每个I/O控制器拥有许多寄存器,这些寄存器用于存储即将被传输的命令和数据。通常,具体的I/O指令允许在这些寄存器和系统内存之间进行数据传输。为了更加便捷的访问I/O设备,许多计算机系统采用了内存映象I/O。这样,内存的一部分地址范围被留出来并映射到设备寄存器中。对设备寄存器的访问就可以通过读写内存地址实现。这种技术适用于视频控制器等能够快速响应的设备。在IBM个人计算机中,显示屏上的每块区域都被映射到内存中相应的区域。在屏幕上显示文本就像往相应的内存映象中写入文本一样简单。
内存映象输入输出也适用于其它一些设备,比如用于将调制解调器和打印机连接到计算机上的串行和并行端口。CPU通过对这些设备的寄存器进行读写来实现与它们的数据传输,这部分寄存器被称为I/O端口。为了通过存储映象串行端口发送一长串字节,CPU首先将数据字节写入数据寄存器,然后在控制寄存器中设置一个标志位来表明数据准备完毕。设备接受到该数据字节后将控制寄存器中的标志位清零以表明准备好接收下一个字节。然后,CPU传输下一个字节。如果CPU以轮询方式检查每一个控制位,那么就有一个(周期)恒定的循环来检查设备是否准备好,这种方式被称为程序控制输入输出(PIO)。如果CPU不对控制位进行轮询检查,而是通过接收中断(设备准备好接收下一个字节时会向CPU发出一个中断)来实现,那么这种数据传输被称为中断驱动。
CPU中的寄存器的访问时间通常是一个CPU时钟周期。大多数CPU能够以每个时钟跳变一个或多个操作的速率完成对指令的解码并实现对寄存器内容的简单操作。主存储器就不同了,它通过存储总线进行数据传输。内存的访问通常需要花费多个CPU时钟周期才能完成,这样,因为缺乏完成指令所需的数据,处理器通常需要停止运行(stall)。由于要频繁的访问内存,这种情形简直忍无可忍。解决方法是在CPU和主存储器间添加快速存储器。一个缓冲存储器可以调节CPU和内存间的速度差异,它被称为高速缓冲存储器,这将在2.4.1节讨论。
2.3.2 磁盘
磁盘为现代计算机系统提供了大容量的辅助存储空间。从理论上讲,磁盘相对来说要简单一些(图2.5)。每个盘片是像CD一样的平坦的圆形物体。盘片直径通常在1.8到5.25英寸之间。盘片的两面覆盖了一层磁性材料。我们通过在盘片上进行磁性记录来存储信息。
图 2.5
一个读写头在每个盘片表面“飞行”。磁头与磁盘取数臂相连,磁盘取数臂作为一个单元控制所有的磁头。盘片表面被划分为圆形的磁道,磁道又被划分为扇区。在同一取数臂位置上的磁道集组成一个柱面。一个磁盘可能由数千个柱面组成,每个磁道又包含了数百个扇区。通用的磁盘驱动器的存储容量由吉度量。
当磁盘运行时,驱动马达高速旋转。大多数驱动器的转速在每秒60到200转之间。磁盘速度分为两部分。传送速率是数据在驱动器和计算机之间的流动速率。定位时间(有时也被称为随机存取时间)由寻道时间和旋转等待时间组成。寻道时间是磁盘取数臂移动到指定柱面所需的时间。旋转等待时间则是指指定的扇区旋转到磁头所需的时间。典型的磁盘的数据传输速率为数兆每秒,寻道时间和旋转等待时间为数毫秒。
因为磁头在盘片上面很薄的一层气垫(其厚度以微米计)上飞行,所以就会有磁头碰到盘片的危险。虽然盘片由一层薄薄的保护膜覆盖着,但有时磁头仍会损伤磁表面。这种事故被称为磁头碰撞。磁头碰撞所造成的盘片损伤是不可修复的;这就需要更换磁盘了。
有种磁盘是可移动的,根据不要可以使用不同的磁盘。可移动磁盘通常有一个盘片组成,这个盘片放入驱动器之前有一个塑料外套来保护它免收损害。软磁盘是一种廉价的可移动磁盘,它用一个软塑料外壳包裹着一个软盘片。软盘驱动器的磁头往往直接接触磁盘表面,所以这种驱动器的转速就要比硬盘慢很多,这样可以减少对磁盘表面的损耗。可移动磁盘的工作方式与硬盘非常相似,其存储容量由兆度量(注:原著认为移动磁盘的容量以吉为单位度量,这可能是个错误)。
软盘驱动器通过一组导线与计算机连接,这组导线被称为输入输出总线。现有多种总线标准,其中包括增强型IDE接口(EIDE)、ATA和小型计算机系统接口(SCSI)。总线上的数据传输通过一个被称为控制器的特殊电子芯片实现。主控制器位于总线末端的计算机中。磁盘控制器构建在每个磁盘驱动器中。为了进行磁盘的I/O操作,计算机将命令发送到主控制器中,通常通过映象内存I/O端口,就像在2.3.1节中所描述的那样。然后主控制器通过消息将命令发送到磁盘控制器,磁盘控制器再运行磁盘驱动硬件来执行该命令。磁盘控制器往往有一个内建的高速缓冲存储器。磁盘驱动器中的数据传输在高速缓冲存储器和磁盘表面进行,然后数据以电子速率传输到主控制器中。
2.3.3 磁带
磁带是一种在早期应用广泛的辅助存储器。虽然它能够长久的存储大量数据,但是与主存储器相比它的读写速度太慢了。另外,磁带的随机读写速度仅仅是磁盘的千分之一。所以磁带不适合作为辅助存储器使用。磁带通常主要用作备份,用来存储不常用的数据以及用于在系统间传输数据。
磁带缠绕在线轴上,通过在读写头前缠绕或反绕进行工作。将磁带移动到所需的地点需要耗费数分钟,但是一旦定位完毕,磁带驱动器的写入速度可与磁盘驱动器相当。根据具体的磁带驱动器,磁带的存储容量很不一样。有些磁带能够存储一张大容量磁盘2到3倍的数据。磁带和其驱动器通常根据宽度分类,这包括:4、8、19毫米和1/4、1/2英寸。
2.2 存储器体系
根据速度和价格,计算机系统中应用的各种各样的存储器系统可以通过一个分级层次结构进行组织(图 2.6)。更高层的存储器价格更贵,速度更快。当我们往该层次下面转移时,通常每位的价格会降低,然而读写周期会增加。这种权衡是有道理的;如果给定的一种存储系统与另外一种相比更快更便宜(其它的特性相同),那么就没有理由选择更贵更慢的存储器。事实上,包含纸带和磁心存储器在内的许多早期的存储器早就进了博物馆了,现在磁带和半导体存储器已经变得更快更便宜。在图2.6中,位于顶端的三层存储器可能半导体存储器。
图2.6
除了速度和价格的不同之外,各种存储系统也有着易失和非易失上的区别。易失性存储器在掉电后会丢失数据。由于缺乏昂贵的电池和备用发电机,必需要将数据写入非易失性存储器中以保证数据的安全存储。在图2.6中所表示的层次结构中,电子磁盘上面的存储系统是易失性的,而下面的是非易失性的。电子磁盘可被设计为易失性的或非易失性的。在正常的操作期间,电子磁盘将数据存储在一个大型的DRAM阵列中,这是易失性的。但是许多电子磁盘驱动器隐含着一个磁硬盘和一个备用电池。如果外部电源被阻断,那么电子磁盘控制器将数据从RAM拷入磁盘中。当外部电源恢复时,控制器又将数据拷回到RAM中。
设计一个完整的存储系统必需权衡以下几个方面:尽可能的提供廉价的非易失性的存储器,只有在必要的情况下才使用昂贵的存储器。在两个组件的访问时间或速率差距很大的情况下可以使用高速缓冲存储器来提高系统性能。
2.4.1 高速缓冲存储技术
高速缓冲存储技术是计算机系统中相当重要的一个概念。数据通常存储在一些存储系统(如主存储器)中。在使用数据时,首先要把它转移到更快速的存储器(高速缓冲存储器)中。当我们需要使用特定的数据片段时,首先检查它是否在高速缓冲存储器中。如果在,就直接读取;否则,就从主存储系统中读取,并向高速缓冲存储器中添加一个备份(这样是为了下次使用这个数据。当然,这只是个假设,我们未必会再次用到它)。
另外,变址寄存器等内部可编程寄存器为主存储器提供了高速的缓冲存储能力。程序员(或编译器)通过实现寄存器分配和替换算法以决定哪些数据保存在寄存器中,哪些保存在主内存中。也有些高速缓冲存储器完全以硬件实现。例如,大多数系统使用一个指令高速缓冲存储器来存储要执行的下一条指令。如果没有高速缓冲存储器,CPU就必须要在从主存储器中取指令时等待几个周期。类似的,大多数系统在其存储体系中拥有一个或多个高速数据缓冲存储器。因为这在操作系统的范畴之外,所以在本书中我们并不关心这种纯硬件的存储设备。
因为受到高速缓冲存储器的容量限制,所以高速缓冲存储器管理的设计是一个相当重要的问题。精心选择高速缓冲存储器的容量和替换策略,这能够使高速缓冲存储器的访问比达到80%到99%之间,将在很大程度上提高系统性能。在第10章中将讨论软件控制的高速缓冲存储器的替换算法。
可以将主存储器看成辅助存储器的高速缓冲存储器,因为辅助存储器的数据必须要拷到主存储器中才能使用,而主存储器中的数据必须要放到辅助存储器中才能安全存储。长期驻留在辅助存储器中的文件系统数据可能会出现在多个存储层次中。在最高层,CPU可能会维护一个高速缓冲存储器来保存主存储器中的文件系统数据。电子式RAM(也成为固态磁盘)可以用作高速存储设备,通过文件系统接口可以实现对它的访问。大容量的辅助存储器是磁盘。反过来,为了预防磁盘故障所造成的数据丢失,磁盘中存储的数据通常备份在磁带或可移动磁盘上。为了降低存储成本,有些系统能够将辅助存储器中的旧文件归档保存到第三方存储器中,如:小型盒式磁带机(jukebox)。
依据硬件设备和操作系统控制软件,数据可能直接或间接的在多个存储层间转移。例如,从高速缓冲存储器到CPU和寄存器的数据传输完全由硬件实现,而不受操作系统的干预。另一方面,从磁盘到内存的数据传输通常受操作系统控制。
2.4.2一致性
在存储器层次体系结构中,同样的数据可能会同时出现在多个层次中。例如:假设文件B中的一个整型数A被加1,而文件B保存在磁盘中。首先,加法操作进程通过一个I/O操作将A调入主存。然后,又将A拷入cache和内部寄存器中。这样,A的拷贝就会出现在多个地方:磁盘、主存、cache和某个内部寄存器(图2.7)。一旦加法操作在内部寄存器中完成,那么内部寄存器中的A的值就与其它存储器中的不同了。只有将A的新值从内部寄存器写回到磁盘后A的值才会相同。
图2.7
在单任务计算环境中,这种策略并不困难,因为总是要将A拷贝到最高层的存储器中进行访问。然而,在一个多任务的环境中,CPU往返于多个进程。如果同时有几个进程要访问A,那么每个进程都必须要获得最近更新的A的值,这一点必须要非常的小心。
在多处理机环境中就更为复杂了,除了要维护内部寄存器之外,每个CPU还有一个本地cache。这样,多个cache中可能会同时保留一个A的拷贝。因为各个CPU并发运行,所以我们必须要确保某个cache中的A的更新立即反映到其它的cache中。这被称为超高速缓存相关性,通常是一个硬件问题(在操作系统层面之下)。
在分布式环境中,这甚至更加复杂。在这样的环境中,相同文件的多个拷贝(或复制品)可以保存在分布在空间内的多个不同的计算机中。因为能够访问和更新这些拷贝,所以我们必须要确保一处的更新尽快的影响到其它的地方。有多种方法可以解决这个问题,我们将在第16章中讨论。