三、虚拟存储器
-
什么是虚拟存储器
运行的程序如果都经过物理内存来执行,一旦执行的程序很大或很多,就会导致内存消耗殆尽。因此可以将程序分段,只有当前执行的片段才在物理内存中,其他的内容放在下一级存储器比如硬盘、闪存中。这样在程序看来就可以使用比物理内存更大的容量 ,这就是虚拟内存。 -
为什么需要虚拟存储器
- 使用虚拟存储器,可以便于程序在处理器中运行,即程序的大小可以超过物理内存的容量,也可以减少物理内存中的碎片,提高物理内存的利用率(多级页表子页表地址可以不连续);
- 给程序编写带来好处,如果直接使用物理内存,同时运行多个程序时就需要为这些程序分别分配地址空间。使用虚拟存储器,每个程序都认为其占有处理器的所有地址空间,可以任意使用处理器的地址资源,程序编写不必考虑地址空间限制,真正运行时由操作系统将物理内存动态分配给各个程序,将虚拟地址转化为对应的物理地址;
- 可以增强程序的保护和共享,因为即使两个程序使用相同的虚拟地址,也会被映射到不同的物理地址,不同程序不会互相改写。当两个程序在不同地址都使用了内核的函数,如printf函数,操作系统在地址转换时会将二者转换为相同的物理地址,即printf函数在物理存储器中的实际地址,实现了程序的共享;
- 实现程序的权限管理,通过在页表中设置页的属性,操作系统和MMU就可以控制每个页的访问权限。
总的来说,虚拟存储器降低了物理存储器的容量需求,为程序编写带来了方便,并有益于程序的保护、共享和权限管理。
-
地址转换
最通用的虚拟存储器的实现方式是基于分页的虚拟存储器,其地址空间以页(page)为单位,典型大小为4KB,相应的物理地空间进行相同大小的划分,以frame为单位。
对于一个虚拟地址VA,VA[11:0]用来表示页内的位置page offset,剩余部分用来表示哪个页(Virtual Page Number,VPN)。对应的物理地址PA,PA[11:0]用来表示frame内的位置frame offset,剩余部分用来表示哪个freme(Physical Frame Number,PFN)。由于页和frame大小一样,所有VA到PA的转换只是VPN到PFN的转换,offset相同。
处理器中专门负责地址转换额部件为内存管理单元(Memory Manage Unit,MMU)。 -
单级页表
页表(Page Table,PT):记录虚拟地址到物理地址(实际上是VPN到PFN)的对应关系。页表项包含物理内存地址、有效位和脏位。- 物理内存地址:实际上不是整个物理地址,只是PFN(Page Offset与Frame Offset相同);
- 有效位:用于判断这个虚拟地址对应的4KB空间是否被映射到物理内存中。
- 脏位:有的页被调入内存后被修改过,标记为脏,如果需要调换这一页,就要把该页写回磁盘。
页表寄存器(Page Table Register,PTR):存放当前程序的页表在物理内存中的起始地址,操作系统将一个程序调入物理内存中执行时,就会将PTR设置好,前提是页表位于物理内存中一片连续的位置。
通过页表进行地址转换的过程:通过PTR找到程序对应页表的起始地址——页表中的表项记录了虚拟地址与物理地址的映射关系,通过虚拟地址找到对应的物理地址。
总结寻址过程:CPU在执行指令的时候首先给出虚拟地址,CPU内MMU根据虚拟地址和页表寄存器查询存放在内存中的页表,根据查询到的记录得到物理页框号PFN,此时MMU再用PFN和虚拟地址的Page Offset组合起来查询内存中数据。
注意,如果页不在内存中,就会触发缺页中断,缺页中断需要调用磁盘,因此需要花费很多时间。一次内存数据的访问实际上对应两次内存访问,第一次访问的是页表,第二次访问的才是页的内容,如果发生缺页,则还需要访问磁盘。
-
多级页表
一个程序实际难以用完整个虚拟内存空间,可能只是用其中的一小部分,这就造成了页表中大部分是空的,形成空间浪费。因此需要使用多级页表的方式进行改进。
多级页表的思想是:将单级页表分为多个小的子页表,执行进程时只根据需求逐步将子页表添加到物理内存中,且不同子页表不需要占用连续的物理内存空间,提高了内存利用率。带来的问题是,需要一个页表来记录子页表的在物理内存中的位置,称为一级页表,子页表称为二级页表。
通过两级页表得到虚拟地址对应的数据,首先需要访问第一级页表,得到虚地址所属第二级页表的基地址,再从第二级页表中得到虚地址对应的物理地址,最后访问物理内存得到数据。
-
Page Fault
当访问页表时PTE中有效位是0,则表示虚拟地址所属的页还没被放到物理内存中,还未形成地址的映射关系,发生了Page Fault。
Page Fault是异常的一种,通常由软件(操作系统)处理而不是硬件。因为Page Fault要访问硬盘,异常处理程序就算需要使用几百条指令,也比访问硬盘的时间少很多;而且将缺失页搬移进物理内存时如果没有空余的空间,就需要进行页替换,使用软件可以使用灵活的算法替换,硬件难以实现。
将缺失页从硬盘搬移到物理内存,但是直接使用虚拟地址不能得到页在硬盘中的位置,因此需要使用一个类似于页表的表格记录页在硬盘中的位置。操作系统会在硬盘中为一个进程开辟一块swap空间用于存放进程的所有页。
物理内存相当于硬盘的Cache,其所有内容都在硬盘中存在,自身自保存最近使用的部分内容。当物理内存中的内容被改变时,硬盘中的内容就过时了。于Cache类似,有写通和写回两种方法处理。写通实际是不可行的,因为硬盘访问非常慢,无法马上将改变的内容写进硬盘,这种方法一般只在L1 Cache和L2 Cache中使用。因此一般使用写回处理,这就需要用一个“脏位”来记录PTE的状态,标志其是否被修改过。
物理内存中页替换,可以使用LRU算法,这就需要用一个“使用位” 记录页是否最近被使用。 -
程序保护
在页表的PTE中加入AP字段,通过AP的不同编码来控制页的访问权限。 -
TLB的设计
- 为什么需要TLB
对于两级页表,需要访问两次物理内存才能得到物理地址,而物理内存相对处理器来说比较慢,因此可以借鉴Cache的设计理念将PET缓存起来,加快地址转换速度,缓存PET的部件就叫TLB(Translation Lookaside Buffer)。缓存的前提是程序是串行执行的,会顺序地从一个页内取指令,也就是现在访问的页,后续也很有可能被访问,其具有时间相关性。 - TLB缺失
当虚拟地址查找TLB时找不到所需的PET时发生TLB缺失。TLB本身的容量很小,缺失频率较高。缺失情况主要有:
1. 虚拟地址对应的页不在物理内存中,页表中没有对应的PTE,TLB自然也没有;
2. 虚拟地址对应的页在物理内存中,页表中存在对应的PTE,但是没有加入到TLB中或者替换出了TLB。
解决TLB缺失就是要将从页表中找到映射关系并写回TLB中,称为Page Table Walk,可以使用软件/硬件方式处理。
- 为什么需要TLB
-
Cache的设计
TLB是加速了虚拟地址到物理地址的转换,快速得到数据再物理内存中的位置;
虚拟Cache是加速了得到数据的过程。因为直接从物理内存中取数据比较慢,可以使用虚拟Cache缓存部分虚拟地址对应的数据,从而直接使用虚拟地址寻址找到数据(发生缺失时还是要通过虚拟地址—TLB/页表—物理地址—数据的过程得到数据)。
参考资料:
《超标量处理器设计》——姚永斌