1.虚拟存储器出现的原因
一个系统中的进程是与其他进程共享CPU和主存资源的,但是共享主存会形成一些特殊的挑战。随着对CPU需求的增长,进程就会慢慢的慢下来。如果同时有太多的进程就需要太多的存储器,一些进程根本就无法运行。存储器还很容易被破坏。还有可能一个进程不小心写了另一个进程使用的存储器,它就可能以某种完全和程序无关的方式失败,这种失败我们很难去查找到其真正原因。
虚拟存储器是为了更有效的管理存储器以及减少出错而产生的。现代系统提供了一种对主存的抽象概念,叫做虚拟存储器(VM)。虚拟存储器是硬件异常,硬件地址翻译,主存,磁盘文件和内核软件的完美交互,它利用了画饼充饥的思想,因为每个进程需要一个一致私有的连续地址空间,它就构建了一个虚拟存储器为进程在该虚拟存储器中分配连续的地址空间,满足了进程的需求,但是它此时为进程分配的地址空间并不是我们真实的物理地址。它通过一个很清晰的机制,提供了三个重要的能力:
1>它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存了活动区域而并非一下为一个进程分配一次活动的所有所需空间,它会根据需要在磁盘和主存之间来回传送数据,从而高效的使用主存。
2>虚拟存储器为每一个进程提供了一致的地址空间,简化了存储器管理。
3>它保护了每个进程的地址空间不被其他进程破坏,极大的降低了由于进程间的互相干扰而产生的不可控结果。
虚拟存储器是计算机系统中最重要的概念之一。它成功的一个主要原因就是因为它是沉默地,自动地工作的,它不需要程序员的任何干涉。
2.物理和虚拟寻址
物理:计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组。每个字节都有唯一的物理地址(Physical Address,PA)。第一个字节的地址为0,接下来的字节地址为1,依此类推。我们把这种方式称为物理寻址。
虚拟寻址:CPU通过生成一个虚拟地址(Virtual Address,VA)来访问主存,这个虚拟地址被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换成物理地址的任务叫做地址翻译(address translation)。就像异常处理一样,地址翻译需要CPU硬件和操作系统间的紧密结合。CPU芯片上叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容由操作系统管理。
3.虚拟存储器作为缓存的工具
虚拟存储器(VM)被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有唯一的一个虚拟地址,这个唯一的虚拟地址是作为到数组的索引的。磁盘上数组的内容被缓存在主存中。VM系统通过将虚拟存储器分割为称为虚拟页(Virtual Page,VP)的大小固定的块来处理这个问题。物理存储器也被分割为物理页(Physical Page,PP),大小也是P字节(物理页也称为页帧(page frame))。
在任意时刻,虚拟页面的集合都分为三个不相交的子集:
1>未分配的:VM系统还未分配(或创建)的页。未分配的块没有任何数据和它们相关联,也就不占用任何的磁盘空间。
2>缓存的:当前缓存在物理存储器中的已分配页。
3>未缓存的:没有缓存在物理存储器中的已分配页。
图中所示的是一个有着8个虚拟页的小虚拟存储器。虚拟页0和3还没有被分配,因此在磁盘上还不存在。虚拟页1,4和6被缓存在物理存储器中。页2,5和7已经被分配了,但是当前并未缓存在主存中。
页表
同任何缓存一样,虚拟存储器系统必须有某种方法来判定一个虚拟页是否存放在DRAM中某个地方。如果是还需要判断它存放在哪个物理页中。如果不命中,系统必须判断这个虚拟页存放在磁盘的哪个位置,在物理存储器中选择一个牺牲页,并将虚拟页从磁盘拷贝到DRAM中,替换这个牺牲页。
这些功能是由许多软硬件联合提供的,包括操作系统软件,MMU(存储器管理单元)中的地址翻译硬件和一个存放在物理存储器中的叫做页表(page table)的数据结构,页表将虚拟页映射到物理页。每次地址翻译硬件将一个虚拟地址转换为物理地址的时候都会读取页表。操作系统负责维护页表的内容,以及在磁盘和DRAM之间来回传送页。
页表就是一个页表条目(Page Table Entry,PTE)的数组。虚拟地址空间中的每个页在页表中一个固定偏移量处都有一个PTE。为了我们的目的,我们将假设每个PTE是由一个有效位和一个n位地址字段组成的。有效位表明了该虚拟页是否被缓存在DRAM中。如果设置了有效位,那么地址字段就表示DRAM中相应的物理页的起始位置,这个物理页中缓存了该虚拟页。如果没有设置有效位,那么一个空地址表示这个虚拟页还未被分配,否则,这个地址就指向虚拟页在磁盘上的起始位置。
Linux虚拟存储器系统
Linux为每个进程维持了一个单独的虚拟空间,如下图: