在虚拟存储器中,如果不采取有效的措施,访问主存储器的速度将要降低几倍。这不符合存储系统的要求,因为在存储系统中,要求系统的访问速度接近于速度最高的那个存储器。造成虚拟存储器速度降低的主要原因是:在段式或页式虚拟存储器中,要访问主存储器必须先查段表或页表,在段页式虚拟存储器中,既要查段表也要查页表。如果段表和页表都在主存储器中,那么,包括访问主存储器本身这一次在内,主存储器的访问速度将要降低2至3倍。
  要想使虚拟存储器的速度接近主存储器的速度。或者说,要想使虚拟存储器能够真正实用,必须加快查表的速度。
  由于程序在执行过程中具有局部性的特点,因此,对页表的访问并不是随机的,在一段时间内,只是局限在少数几个存储字内。根据这一特点,可以把经常访问的页面地址存放在一个小容量的高速存储器中,称为"快表",当快表中查不到时,再从存放在主存储器中的页表中查找实页号。与快表相对应,存放在主存储器中的页表称为慢表。慢表是一个全表,快表只是慢表的一个副本,而且只存放了慢表中很少的一部分。
  实际上,快表与慢表也构成了一个由两级存储器组成的存储系统。与虚拟存储器和Cache存储器类似。在这个快慢表的存储系统中,访问速度接近于快表的速度,存储容量是慢表的容量。
  快表在英文资料中称为TLB(Translation Lookaside Buffer),有些中文资料中翻译成地址变换后行缓冲器,或地址转换后备缓冲存储器等。
  由快慢表构成的虚拟存储器的地址变换过程如图5.15所示。用多用户虚页号同时去查快表和慢表。由于快表的查表速度要比慢表快得多。如果在快表中查到与多用户虚地址相等的存储字,就立即终止慢表的查表过程,并读出该存储字中的实页号p送入到主存储器的地址寄存器中。如果在快表中没有查到,就到存放在主存储器中的慢表中去找。如果在慢表中查到了,则把查到的实页号p送入主存储器的地址寄存器,同时,也把这个实页号连同多用户虚地址等信息送入快表中。这时,若快表已满,则要采用某种替换算法,替换掉其中一个不常用的存储字。
  由于快表的查表速度非常快,与主存储器的一个存储周期相比几乎可以忽略不计。因此,只要快表的命中率很高,那么,虚拟存储器的访问速度就能与主存储器的工作速度很接近。
  在采用快慢表结构的虚拟存储器中,要提高快表的命中率,最直接的办法是增加快表的容量。快表的容量越大,命中率就越高。但是,由于快表是按相联方式访问的,当快表的容量增加时,它的查表速度就会降低。那么,能不能让快表不采用相联方式访问,而采用普通的按地址来访问呢?
  如果要在一个按地址访问的存储器中查找一个信息,可以有顺序查找法、对分查找法和散列查找法等。其中,散列(Hashing)查找方法的速度最快。对于快表来说,就是要把多用户虚页号Pv变换成快表地址A。函数关系是:
  Ah=H(Pv)
  散列函数的种类很多。由于快表中的散列函数必须用硬件来实现,因此,通常采用一些简单的函数关系,如折叠按位加散列函数等。
  由于把一个大的多用户虚页号Pv散列变换成了一个小的快表地址Ah,因此,必然会有很多个多用户虚页号Pv都散列变换到相同的快表地址Ah中,这种现象称为散列冲突。为了避免因散列冲突而发生查快表错误,必须把多用户虚页号也加入到快表中去,并且与主存实页号存放在同一个快表存储字中。另外,还要用一个比较器,把从快表中读出来的多用户虚页号与多用户虚地址中多用户虚页号进行比较。
图 5.15 采用快慢表的地址变换过程
  采用散列变换实现快表按地址访问的虚拟存储器如图5.16所示。首先把多用户虚地址中的多用户虚页号Pv(由U和P拼接而形成)送入硬件的散列变换部件,经散列变换后得到快表地址Ah。然后用地址Ah访问快表,读出主存实页号p和多用户虚页号Pv'。把主存实页号p送入主存储器的地址寄存器,与页内偏移d直接拼接形成主存地址,并且用这个地址访问主存储器。同时,把读出的多用户虚页号Pv'与多用户虚地址中多用户虚页号Pv在相等比较器中进行比较。如果比较结果相等,就继续刚才的访问主存储器的操作,否则,立即终止访问主存储器的操作。比较结果不相等表示发生了散列冲突,这时,需要去查存放在主存储器中的慢表。
  由于快表是按地址访问的,在保证访问速度的前提下,它的存储容量可以比用相联存储器实现的快表大很多倍。虽然也需要有一次相等比较,但相等比较可以与访问存储器的操作同时进行。因此,这种快表按地址访问的快慢表结构,与上面介绍的采用相联存储器做快表的快慢表结构相比,快表的命中率要高很多,而且查表的速度也很快。
图 5.16 采用散式变换实现快表按地址访问
  下面,介绍一个在实际计算机系统中使用的虚拟存储器快表慢结构及地址变换过程。
  图5.17是IMB370/168计算机的页式虚拟存储器,虚拟地址共长36位。其中,页面大小为4K字节,占12位。每个用户(或每道程序)最多允许占用4K个页面,因此,虚页号也占12位。最多允许16G个用户(或16G道程序)同时上机,用户号占24位,但是,实际上在一段时间内同时上机的用户数(或程序道数)一般不超过6个。
  快表按地址访问,快表的地址由多用户虚页号经硬件的散列变换部件压缩后生成。快表地址共6位,因此,快表容量为64个存储字。
  IMB370/168计算机的虚拟存储器采用了两项新的措施。一项是在快表的每一个存储字中存放两对多用户虚页号与主存实页号,并采用两个相等比较器。只要其中有一个比较器的比较结果相等,就认为快表命中,这时,把命中的实页号p送到主存地址寄存器中,与地址寄存器中的页内偏移拼接成主存实地址。只有当两个比较器的比较结果都不相等时,才认为快表没有命中,需要到慢表中去查主存实页号p。查慢表的方法与前面介绍的方法相同。第二项措施是用一个由6个寄存器组成的相联寄存器组把24位的用户号U压缩成3位的ID。把这个ID与虚页号直接拼接起来作为散列变换部件的输入,这样做能够减少散列部件的输入与输出位数的差,从而降低散列冲突。
  在地址变换开始时,把多用户虚地址中的用户号U与相联寄存器组中的6个用户号U1至U6逐个比较。如果有相等的,就读出对应的3位ID,并把这3位ID与多用户虚地址中的12位虚页号P直接拼接成15位,用这15位作为散列变换部件的输入。这样,在快表中可以同时保留6个用户(或6道程序)的常用页表。在6个用户或程序之内切换时,仍能保持很高的快表命中率。如果用户号U与6个相联寄存器的比较结果都不相等,则表示有6个之外的新用户进入。这时,需要用替换算法把一个不常进入的用户替换出相联寄存器组。只要替换算法好,就能保证经常进入的用户,或系统服务任务被一直保留在相联寄存器组中或很少被替换出去。
图 5.17 IBM370/168 计算机的虚拟存储器快表结构
  目前,许多计算机系统的虚拟存储器都采用象IBM370/168机器类似的方法。包括相联寄存器组,硬件的散列压缩,快慢表结构和多个相等比较器等。而且,所有这些措施对应用程序员来说都是透明的。