Modern Operating System 4th 中译

内存

计算机中第二重要的部分就是内存。理想情况下,内存应当足够快(应当比CPU执行任何指令都要快,这样CPU才不会受限于内存),足够大并且相当便宜。然而目前还没有什么技术可以实现全部的目标,所以必须使用别的方法。内存系统是构建在多层体系上的,如图1-9。最高层的主存有最高的速度,容量较小并且每bit价格最高。

最高层包括了CPU内部的寄存器。它们与CPU一同制造并且同CPU一样快,因此可以认为访问它们是没有延迟的。在32位CPU中它们的典型容量是32x32bits,64位CPU中是64x64bits。无论如何都小于1KB。程序必须自行管理(例如决定它们用来存什么)寄存器。

接下来是缓存,一般由硬件控制。主内存被分为缓存行(cache line),一般每行64bits,如地址0~63为line 0,64~127为line 1。使用量最大的行被调入接近CPU的高速缓存。当程序需要访存时,缓存硬件检查需要的行是否已经在缓存中。如果在,就称为缓存命中(cahce hit),需要的数据可以直接送给CPU而不需要耗费大量时间通过内存总线访问主内存。由于价格高昂,缓存大小也很有限。有些计算机有二级甚至三级缓存,每一级都比上一级更大但也更慢。

在计算机科学中缓存技术是非常重要的,不仅仅是内存的缓存。当一种资源可以被分割,并且其中一部分比另一部分使用的概率更大,那么缓存技术就经常被用来提升性能。操作系统中经常用到类似技术。例如,多数操作系统在内存中保存着频繁访问的文件(或者一部分)以避免一遍遍从硬盘读取。与此类似,长目录名,例如 /home/ast/projects/minix3/src/kernel/clock.c,到磁盘物理地址的转换结果,也被缓存到内存中以避免频繁的查询。最后,一个WEB页面(URL)转换为网络地址(IP地址),结果也会被保存以未来使用。其他的用处不一一例举。

在任何一种缓存系统中,有几个问题很容易遇到,包括:

  1. 何时将新的内容放入缓存。
  2. 将新的内容放到缓存哪一位置。
  3. 需要空闲空间时移除缓存中的哪一部分。
  4. 缓存中赶出的数据放到主存的哪一部分。

并不是每一个问题都与任何缓存情况相关。对于主内存的CPU缓存,一般每产生一个缓存未命中,就会有新的内容进入缓存。一般将要使用的缓存行是通过一些确定的内存地址引用比特计算出来的。例如4096 x 64的32位地址缓存中,位6至17可能被用来指定缓存行,0~5比特是行内的比特。在这种情况下,将要移除的项和将要插入的项是同一个位置,但是在其他的系统上则未必。最后,当修改后的数据重新写回主存时,就涉及到之前提到的回写地址的问题。

(待改进) Not every question is relevant to every caching situation. For caching lines of main memory in the CPU cache, a new item will generally be entered on every cache miss. The cache line to use is generally computed by using some of the high-order bits of the memory address referenced. For example, with 4096 cache lines of 64 bytes and 32 bit addresses, bits 6 through 17 might be used to specify the cache line, with bits 0 to 5 the byte within the cache line. In this case, the item to remove is the same one as the new data goes into, but in other systems it might not be. Finally, when a cache line is rewritten to main memory (if it has been modified since it was cached), the place in memory to rewrite it to is uniquely determined by the address in question.

缓存对性能的提升如此之大,以至于现代CPU一般都有2个缓存。第一级缓存,或者说L1 Cache,总是在CPU内部并且通常为CPU内部的执行引擎解码指令服务。多数CPU有第二个L1缓存,用于重度使用的数据。典型的L1大小是16KB。另外通常还有一个二级缓存,称为L2 cache,保存着最近使用的内存中的几兆字节的数据。L1与L2时间上的区别是,访问L1缓存通常没有延迟,然而访问L2缓存一般有一到两个时钟周期的延迟。

在多核心芯片中,设计师必须决定缓存应该放在哪里。在图1-8(a)中,只有一个L2缓存并且被所有核心共享。Intel的多核心芯片通常采用这种方式*1。与此相反,如图1-8(b)所示,每个核心都有独立的二级缓存,这种方式通常被AMD采用。两个策略各有优劣。例如,Intel的共享L2要求更复杂的缓存控制器但是AMD的方式使得保持L2的一致性变得更加困难。

主内存在图1-9等级的下一层。这一层是内存系统中工作最重的。主内存一般被称为RAM(Random Access Memory,随机存储器)。以前也被称为core memory,因为大约在50~60年代的计算机使用铁氧体磁芯作为主内存。磁芯内存早已消失但是称呼还是留了下来。现在的内存一般有几百兆至几GB并且正在快速增长。所有CPU要求而不能放在缓存的数据均被放在主内存。

除了主内存,许多计算机都有少量的非易失随机存储器。与RAM不同,非易失随机存储器中保存的数据断电后不会丢失。ROM(Read Only Memory,只读存储器)通常在设备出厂时被编程并且内容不能更改。它读取很快并且并不昂贵。在一些计算机中,启动所需的启动引导器(bootstrap loader)就被写在ROM中。同样的道理,一些I/O卡也自带ROM用于低级设备控制。

EEPROM((Electrically Erasable PROM,电可擦写只读存储器)和Flash存储器也是非易失性的,但是与ROM不同的是它们可以被擦除重写。然而相比于RAM,它们的擦写需要大量的时间,所以它们一般是和ROM一样的用途,只是在程序发现bug时可以重写它们。

Flash也被经常用于便携电子设备的存储介质。它们可以在数码相机中存储照片视频,或者是在MP3中存储歌曲音乐。Flash的速度介于RAM和磁盘之间。另外,与磁盘不同,Flash擦写次数过多就会磨损。

另外一种记忆体是CMOS,也是易失性存储。大多数计算机使用CMOS储存当前的时间。CMOS内存和计时时钟由一枚小电池供电,所以即使计算机断电时钟依旧不会停止。CMOS内存也保存着一些配置参数,例如开机时应当从哪个磁盘启动。使用CMOS的原因是CMOS内存极为省电,即使是计算机出厂配置的电池也可以工作数年。然而如果电池没电,计算机就像得了老年痴呆一样遗忘它已记住数年的设置,例如从哪个磁盘启动等


*1:近年的Intel CPU每个核心均有独立的L1,L2缓存,所有核心共享L3缓存