虚拟地址向物理地址的转换

每个程序员都梦想拥有这样的内存:它是私有的、容量无限大的、速度无限快的,并且是永久性的存储器(即断电时不会丢失数据)。计算机中的存储层次结构都是在考虑性价比的前提条件下尽量满足程序员的这一需求,其中虚拟地址的产生在其中起到了至关重要的作用:它允许程序员不用考虑物理内存的使用情况而任意使用整个内存空间(CPU地址总线决定)。

总体概述


va_pa.png

首先CPU从指令中获取到虚拟地址,然后该虚拟地址交给MMU,通过MMU中的TLB索引物理地址,如果TLB不存在该虚拟地址的entry,则到物理内存中对应的页表中查找,如果页表项存在,则可以根据页表项找到物理地址,并更新TLB,接着根据指令类型和页表项位标识读写cache/mem,如果页表项不存在就会产生缺页异常。

页表项结构

page_table.png
可以看到虚拟地址包括:虚拟叶号(VPN)和偏移地址
而虚拟叶号中包括:叶项有效位,访问控制位(RW)和物理帧号(PFN)
重新划分后可以得到物理地址:物理帧号和偏移地址

缺页异常

page_fault.png

MMU根据虚拟地址查找页表项,如果对应页表项无效(有效位标记)则就会产生缺页异常,此时MMU会从内存匿名池中获取一帧内存,更新页表项信息,然后从Disk中搬移数据填充。如果内存已全部使用完,则需要根据替换策略替换出一帧内存,并跟新页表项。 

不同的层次结构

virtual_physical_cache.png
物理cache:因为采用TLB管理,有很好的替换策略,对于命中率不高、需要频繁切换的应用效率比较高。
虚拟cache:cache命中率比较高(单线程优)时采用虚拟cache,因为地址翻译延迟很高,不能充分发挥cache的优势。
虚拟-物理cache:减少了关键路径,少见。

补充

OS产生之前我们基本采用手动分配内存,而对于未知的应用又没法定义应用所使用的内存的范围,OS之后的虚存可以对内存进行妥善的管理,使通用性大大增强,并可以保证多个任务顺利安全的进行。(域的管理用的比较少)
对于每个应用都存在0~3G的用户空间内存,应用可以采用连续的某一段虚拟地址进行访存,其中内存的分配:代码段+常量数据段+全局数据段,按顺序一层层生长,堆数据也同样往上长,栈数据往下压。
随应用进程产生虚拟地址从匿名池(空闲内存管理池)中申请物理内存与虚拟地址关联,应用进程关闭,物理内存得到释放(取消关联)。

疑问点

  1. 我们常说的用户空间(0~3G)和内核空间(3~4G)指的是虚拟地址空间还是物理地址空间?

  2. 如果“疑问点1”中的空间是指物理地址空间,是不是可以说程序员写程序时可以使用内核空间?