我们知道,一个简单的计算机系统模型是CPU执行指令,而存储器为CPU存放指令和数据。
在简单模型中,存储器系统是一个线性的字节数组,CPU能够在常数时间范围内访问每个存储器位置。这样的一个简单模型并不能有效地反映现代系统实际工作的方式。
实际上,存储器系统是一个具有不同容量,成本和访问时间的存储设备的层次结构。CPU寄存器保存着最常用的数据。靠近CPU的小的快速的高速缓存存储器
作为一部分存储在相对慢速的主存储器(简称主存)中的数据和指令的缓冲区
。主存暂时存放 存储在容量较大的慢速的磁盘上的数据。而这些磁盘又常常作为存储在通过网络连接的其他机器的磁盘或磁带上的的数据的缓冲区域。
值得注意的是,高速缓存存储器是作为CPU和主存之间的缓存区域,它们对应用程序的性能影响最大。
存储技术:
1.随机访问存储器(RAM):
随机访问存储器分为两类,静态的(SRAM)和动态的(DRAM)。静态的比动态的快,但是也贵的多。
SRAM用来作为高速缓存存储器,既可以在CPU上,也可以在CPU下。 DRAM用来作为主存,也用来作为图形系统的帧缓冲区。典型地,一个桌面系统的SRAM不会超过几兆,但是DRAM却有几百兆或者几千兆。
为了更好的说明DRAM和SRAM的特性和差异,在这里做个对比:
a.
SRAM将每个位存储在一个双稳态的存储器单元里。每个单元是用一个六晶体管电路来实现的。这个电路有这样一个属性,它可以无限期地保持在两个不同的电压配置或状态之一。它的稳定性很好,也就是说,只要有电,它就会永远保持地保持它的值。即使有干扰(例如电子噪音),来扰乱电压,当干扰消除时,电路就会恢复到稳定值。
b.
DRAM 将每个位存储为对一个电容的充电,这个电容非常的小。DRAM存储器可以制造得非常密集:
每个单元由一个电容和一个访问晶体管组成。但是,与SRAM不同,DRAM存储器单元对干扰非常敏感,当电容的电压被扰乱之后,它就永远不会恢复了。暴露在光线下会导致电容电压改变。很多原因导致漏电,使得DRAM过阵子又会失去电荷,所以它是不连续的。存储器系统必须周期性地通过读出,然后重写来刷新存储器的每一位。 c.
SRAM 不需要刷新,它的存取比DRAM快,对诸如光和电噪声这样的干扰不敏感。代价是,SRAM比DRAM使用更多的晶体管,因而密集度更低而且更贵功耗更大。
好了,基于上面的简单介绍,下面我们来讨论一下传统的DRAM:
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">DRAM 芯片中的单元是 :位. DRAM中的所有位被分成d个超单元. 每个超单元都由w个位组成. 也就是说,一个d×w的DRAM总共存储了dw位信息.</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
每个超单元有形如(i,j)的地址,这里i表示行,j表示列。
信息通过引脚的外部连接器
流入和流出芯片,每个引脚携带一个位的信号。2位的行和列超单元地址由2个addr引脚携带。
下面一个128位的16×8的DRAM芯片的高级视图,带阴影的方框表示(1,1)处的超单元:
其中,有d=16个超单元,每个超单元有w=8位。
每个DRAM芯片被连接到某个称为 存储控制器的电路
,这个电路可以一次传送w位(一个超单元的内容)到每个DRAM芯片或一次从每个DRAM传出w位。
为了描述这个传送和传出过程,我简单做了一个过程说明图,如下:
存储控制器将行地址发送DRAM,然后是列地址。DRAM把超单元(1,2)的内容发给控制器作为响应。
另外,注意RAS和CAS请求共享相同的DRAM地址引脚。电路设计者们将DRAM组织成二维阵列而不是线性数组的一个原因是降低芯片上引脚的数量,它的缺点是必须分两步发送地址,这增加了访问时间。
接着上次简单的介绍,让我们来继续讨论这些“存储器们”吧。
在上一篇中我提到了传统的DRAM,简单描述了每个DRAM芯片与存储控制器的“交互”过程。下面,我们来看一下多个DRAM芯片是怎样集合在一起工作的。
存储器模块:
DRAM 芯片包装在存储器模块中,这个存储器模块是插到主板的扩展槽上的。常见的包装包括168个引脚的双列直插存储器模块(DIMM)
,它以64位为块传送数据到存储控制器和从存储控制器传出数据,还包括72个引脚的单列直插存储器模块(SIMM)
,它以32位为块儿传送数据。
为了展示一个存储器模块的基本思想,用一个 8个64Mbit的DRAM芯片
的模块做示例,我简单做了一个过程图,如下:
在这里,每个超单元存储主存的一个字节,而用相应超单元为(i,j)的8个超单元来表示主存中字节地址A处的64位双字。
要取出存储器地址A处的一个64位双字,存储控制器
将A转换成一个超单元地址(i,j),并将它发送到存储器模块,然后存储器模块
再将i和j广播到每个DRAM
。作为响应,每个DRAM输出它的(i,j)超单元的8位内容。模块中的电路收集这些输出,并把它们合成一个64位双字,再返回给存储控制器。
另外,通过将多个存储器模块连接到存储控制器,能够聚合主存。在这种情况下,当控制器收到一个地址A时,控制器先选择包含A的模块k,将A转换成它的(i,j)形式,并将(i,j)发送到模块k。
下面,我们来看几个增强的DRAM:
快页模式 DRAM(FPM DRAM):
传统的DRAM将超单元的一整行拷贝到它的内部行缓冲区,使用一个然后丢弃其余的。而FPM DRAM允许对同一行连续地访问,可以直接地从缓冲区得到服务。例如,要从传统DRAM的同一行中读取四个超单元,则存储控制器必须重复发四个RAS/CAS请求,即使行地址i在每个情况中都是一样的。而要从一个FPM DRAM的同一行读取四个超单元,存储器发送第一个RAS/CAS,后面跟三个CAS请求。也就是一个RAS四个CAS。第一个超单元和传统的一样,剩下的三个,只需要根据CAS在行缓冲区获得就行了。显然获得剩下的三个超单元比获取第一个快。
同步DRAM(S DRAM):
像传统DRAM、FPM DRAM 等都是异步的DRAM,相之下,S DRAM 能够比它们更快地输出超单元的内容。
好了,对随机访问存储器(RAM)的简单介绍我们就先进行到这里,下面我们来看一些其他的存储器:
非易失性存储器:
如果断电,DRAM和SRAM会丢失它们的信息,从这个意义上说,它们是易失的。而非易失性存储器是即使在断电后,也仍然保存着它的信息。现在有很多种非易失性存储器。
我们先来看一种常见的非易失性存储器 ROM:
虽然ROM中有的类型既可以读也可以写,但是它们整体上都称为只读存储器。ROM是以它们能够被重写的次数和对它们重写所用的机制来区分的。
常见的ROM 有以下几种:
PROM(可编程ROM):
只能被写一次,PROM的每个存储器单元有一种熔丝,它只能用高电流熔断一次。
可擦可写ROM(EPROM):
有一个透明的石英窗口,允许光达到存储单元。紫外线光照射过窗口,EPROM单元就被清零。对EPROM编程是通过使用一种把1写入EPROM的特殊设备来完成的。EPROM能够被擦除和重编的次数的数量级可以达到1000次。
EEPROM(电子可擦除ROM):能够被编程的次数达到100000。
存储在ROM设备中的程序通常称为固件。当一个计算机系统通电后,它会运行存储在ROM中的固件。PC上的BIOS(基本输入/输出系统)的例程就在固件中。还有一些复杂设备,如图形卡和驱动控制器,也依赖固件翻译来自CPU的I/O请求。
总线:
下面我们来先引入一个总线
的概念,首先,总线到底是什么?它在计算机系统中又扮演着一个什么样的角色呢?
总线 是贯穿整个系统中的一组电子管道,它携带信息字节并负责在各个部件间传递。也可以说,总线是一组并行的导线,能携带地址、数据和控制信号。通常总线被设计成传送定长的字节块(字)。每个I/O设备都通过一个控制器或适配器与总线相连。
控制器:
控制器是置于I/O设备本身的或者系统的主印制电路板(通常称为主板)上的芯片组。 适配器:
适配器是一块插在主板插槽上的卡。
控制器和适配器的功能
都是在I/O总线和I/O设备之间传递信息。
既然提到这里,就顺便介绍一下主存吧。
主存:主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说,主存是由一组动态随机存储器(DRAM)
芯片组成。
访问主存:
我们先来看一个简单的主存访问模型图:
数据流通过总线的共享电子电路在处理器和DRAM主存之间来来回回。
从主存传送数据到CPU的过程叫做读事务,从CPU传送数据到主存的过程叫做写事务。着一系列传送数据的步骤称为总线事务
。
系统总线:连接CPU和I/O桥。
存储器总线:连接I/O桥和主存。
I/O桥:将系统总线的电子信号翻译成存储器总线的电子信号 和
将存储器总线信号翻译成系统总线信号。
后面我们将会介绍,I/O桥也将系统总线和存储器总线连接到I/O总线。像磁盘和图形卡这样的I/O设备共享I/O总线。
下面,我们来看一个典型的连接CPU和主存的总线结构图:
根据这个简单的模型图,我们来简单描述一下读事务和写事务的大致过程:
读事务:
当要从内存中读数据到CPU时,假设这里的地址是A,那么读事务的目标就是把A的内容加载到寄存器文件中。
可简单分为四个步骤:
<code class="hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">CPU把地址放到系统总线,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">I</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">O</span>桥将信号传递到存储器总线。 主存感受到存储器总线上的信号,从存储器总线上读出地址A,从DRAM中的地址A处 (存储控制器地址A转换成超单元地址)取出数据字,放到存储器总线上。 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">I</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">O</span>桥将存储器总信号翻译成系统总信号传递给系统总线。 CPU感觉到系统总线上的数据,从总线上读出数据,并拷贝到寄存器文件中。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
写事务:
和上面的读相逆,这里,寄存器文件的内容被写到地址A,CPU发起写事务。
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">首先,CPU将地址放到系统总线上。传递给存储器总线。 存储器从存储器总线读出地址,并等待数据到达。 CPU将数据字拷贝到系统总线,传递给存储器总线。 主存从存储器总线读出数据字,并将这些位存储到DRAM中。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
好了,这里插入的一点关于硬件过程的描述就先到这里。
下一次,我们来具体详细地讨论磁盘的基本构造以及存储方式。