在日常的编程中,我们简单的把存储器系统看成一个线性的字节数组,但实际的存储系统并不是这样的。
存储器系统是一个由具有不同容量,不同成本,不同访问时间的若干存储设备组成的层次结构,从上到下依次是:寄存器,高速缓存存储器,主存,硬盘,网络文件。层次越高,容量越小,成本越高,访问时间越短,高层的存储设备是底层存储设备的缓存区。这样,一个编写良好的程序总是倾向于频繁的访问某一个层次上的存储设备。这样,整体效果就是一个大的存储池,其单位成本与最底层的存储设备相当,但是访问速度却可以达到最高层的存储设备。
程序员需要理解存储器的这种层次结构,因为这对程序的性能有很大的影响,比如如果数据存储在寄存器中,那么在一个时钟周期内就能访问,如果存储在高速缓存中,那么需要1-30个周期,如果放在内存中,需要50-200个周期,放在磁盘上需要几千万个周期。
程序的“局部性”属性,使得这种层次结构得以可行,局部性是指:程序倾向于多次访问相同的数据项,或者是倾向于访问临近的数据项。
一:存储技术
1:随机访问存储器
随机访问存储器:RAM,分为两类,静态的(SRAM)和动态的(DRAM)。静态RAM相比动态RAM来说,速度更快,价格更高,因此SRAM常用来作高速缓存存储器,而DRAM常用来作内存。
2:DRAM芯片的简单原理
DRAM芯片中的单元(位)被分成了d个超单元(字),每个超单元都是由w个位组成的。因此总位数就是d*w.
这d个超单元,被组织成了r行c列的长方形阵列,所以d=r*c。这样,每个超单元就可以用(i,j)这样的地址来索引,i表示行,j表示列。
比如一个16*8的DRAM芯片,d=16,w=8。可以组织成4*4=16的阵列,这样,地址信息用2位来传输就可以了,因为2^2=4,数据信息用8位来传输。
每个DRAM芯片都连接到存储控制器,为了读出超单元(i,j)的内容,存储控制器将行地址i发送到DRAM,然后是列地址j,然后DRAM把该地址的内容发送给控制器。行地址i称为RAS请求,列地址j称为CAS请求。RAS请求和CAS请求使用相同的地址引脚。
比如,要读出(2,1)的内容,存储控制器先发送行地址2,此时,DRAM就把行2的整个内容都拷贝到一个内部行缓冲区中,接下来存储控制器发送列地址1,DRAM就把行缓冲区中的单元(2,1)发送给存储控制器。
之所以要把DRAM芯片组织称二位阵列而不是线性数组的结构,是因为这样可以减少地址引脚的数量,缺点是必须分两次传送地址信息。
为了跟上迅速增长的处理器速度,DRAM生产商会定期的推出改进的DRAM存储器。它们基于传统的DRAM最初了改进。
3:非易失性存储器
RAM如果掉电的话,就会失去存储内容,因此他们是易失的。而非易失性存储器,即是在掉电后仍然可以保存信息。由于历史的原因,虽然ROM中有的类型可读也可写,但是还是称他们为只读存储器。ROM以能够重写的次数和重写使用的机制进行区分。
PROM,只能被写一次,
EPROM可以被擦写多次,另外还有EERPROM。
一般ROM的用处是存储“固件”,当计算机上电后,会首先运行ROM中的固件,比如BIOS。
4:访问主存
处理器和DRAM主存之间,通过总线来进行交互,CPU和主存之间的数据传送通过一系列的步骤来完成,这些步骤成为总线事务,读事务是主存传送数据到CPU,写事务是CPU传送到主存。
总线是一组并行的导线,能携带地址,数据和控制信号。在实际的计算机系统中,CPU和主存之间的交互需要经过IO桥芯片组,存储控制器就在其中,系统总线连接CPU和IO桥,存储器总线连接IO桥和主存。见图:
IO桥的作用就是将系统总线的电子信号翻译成存储器总线的电子信号。
比如一个指令:movl A, %eax
将地址A的内容加载到寄存器eax中,CPU发起读事务,读事务由三个步骤组成,首先CPU将地址A放到系统总线上,然后IO桥将信号传送到存储器总线,然后存储器接收到存储器总线上的地址信息,读出地址&#x