9.虚拟内存

Vitrual Memory

Posted by HustDsy on September 23, 2020

虚拟内存提供了三个重要的能力: 1)它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存。2)它为每个进程提供了一致的地址空间,从而简化了内存管理。3)它保护了每个进程的地址空间不被其他进程破坏。

9.1物理和虚拟寻址

计算机系统的主存被组织成一个由$M$个连续的字节大小的单元组成的数组。每字节都有一个唯一的物理地址($Physical\ Address$)。$CPU$访问内存最自然的方式就是使用物理地址,这就被称作为物理寻址($physical\ addressing$)。

image-20200923163421530

现代处理器使用一种称为虚拟寻址($virtual\ addressing$,VA)的寻址形式访问主存。虚拟地址在被送到内存之前需要先转换成适当的物理地址,这段过程称为地址翻译($address \ translation$).$CPU$芯片上叫做内存管理单元($Memory \ Management\ Unit,MMU$)的专用硬件,利用存放在主存中的动态查询表来动态翻译虚拟地址,该表的内容由操作系统管理。

9.2地址空间

地址空间($address\ space$)是一个非负整数地址的有序集合:

\[\{0,1,2,...\}\]

如果地址空间是连续的话,那么我们说它是一个线性地址空间($linear address space$)。为了简化讨论,我们假设使用的是线性地址空间。在一个带虚拟内存的系统中,$CPU$从一个有$N=2^n$个地址的地址空间中生成虚拟地址,那么这个地址空间称为虚拟地址空间

\[\{0,1,2,...,N-1\}\]

这也被称为$n$位地址空间。一个系统还有一个物理地址空间($physical\ address\ space$),对应于物理内存的$M$个字节:

\[\{0,1,2,...,M-1\}\]

地址空间的概念是很重要的,因为它清楚地区分了数据对象(字节)和它们的属性(地址)。一旦认识到了这种区别,那么我们就可以将其推广,允许每个数据对象有多个独立的地址,其中每个地址都选自一个不同的地址空间。这就是虚拟内存的基本思想。主存中的每字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址。

9.3 虚拟内存作为缓存的工具

虚拟内存可以看做存储在磁盘上的字节序列,存储在磁盘上的虚拟内容缓存在$DRAM$中。磁盘上的数据被分割为块,这些块作为磁盘和主存之间的传输单元。系统将虚拟内存分割为虚拟页($Virtual\ Page,VP$)的大小固定块来处理这个问题,每个虚拟页的大小为$P=2^p$字节。物理内存也被分割为物理页($Physical\ Page,PP$),大小也为$P$字节,物理页也被称为页帧($page \ frame$)。在任意时刻,虚拟页面的集合都分为三个不相交的子集:

  • 未分配的: VM系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间。
  • 缓存的:当前已缓存在物理内存中的已分配页。
  • 未缓存的:未缓存在物理内存中的已分配页。

image-20200923172303820

9.3.1页表

$MMU$(内存管理单元)中的地址翻译硬件和一个存放在物理内存中叫做页表($page\ table$)的数据节后,页表将虚拟页映射成物理页。每次地址翻译硬件将一个虚拟地址转换为物理地址是,都会读取页表。操作系统负责维护页表的内容,以及在磁盘和$DRAM$之间来回传送页。其中页表就是一个页表条目($Page\ Table\ Entry,PTE$)数组构成。

image-20200923173433000

上图展示了可以看出$VP1,2,4,7$当前缓存在物理内存中,$VP3,6$当前为缓存,而$VP0,5$此时还未分配。DRAM缓存是全相连的,所以任意物理页都可以包含任意虚拟页

9.3.2页命中

当我们读取$VP2$时,我们首先看到有效位是否为1,之后使用$PTE$中的物理内存地址(改地址指向$PP1$中缓存也的起始位置),构造出这个字的物理地址。

image-20200923174413997

9.3.3缺页

在虚拟内存的习惯说法中,$DRAM$缓存不命中称为缺页($page \ fault$)。比如我们现在虚拟地址需要读取$VPN3$这一部分的数据,但是由于有效位为0,这就造成了一个缺页。

image-20200923195548040

这时候需要在物理内存中寻找替换页,这里假定是$VPN4$,首先看它有没有被修改,如果修改的话就写会磁盘,修改有效位为0。之后内核从磁盘复制$VP3$到内存的$PP3$,之后更新页表,之后返回。再重复执行刚刚缺页的指令。

image-20200923195620361

9.3.4分配页面

图9-8展示了当操作系统分配一个新的虚拟内存页对我们示例页表的影响。比如调用用$malloc$的结果。在这个示例中,$VP5$的分配过程是在磁盘上创建空间并且更新$PTE5$,使它指向磁盘上这个新创建的页面。

image-20200923195958569

9.4虚拟内存作为内存管理的工具

  • 简化链接:独立的地址空间允许每个进程的内存映像使用相同的基本格式,而不管代码和数据实际存放在物理内存的何处
  • 简化加载:虚拟内存还使得容易向内存中加载可执行文件和共享对象文件。要把目标文件中.text和.data节加载到一个新创建的进程中, Linux加载器为代码和数据段分配虚拟页,把它们标记为无效的(即未被缓存的),将页表条目指向目标文件中适当的位置。加载器从不从磁盘到内存实际复制任何数据。在每个页初次被引用时,要么是CPU取指令时引用的,要么是一条正在执行的指令引用一个内存位置时引用的,虚拟内存系统会按照需要自动地调入数据页。
  • 简化共享:独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制。一般而言,每个进程都有自己私有的代码、数据、堆以及栈区域,是不和其他进程共享的。在这种情况中,操作系统创建页表,将相应的虚拟页映射到不连续的物理页面。
  • 简化内存分配:虚拟内存为用户进程提供了一个简单的分配额外内存的机制。当一个运行在用户进程中的程序要求额外的堆空间时,操作系统分配一个适当的数字(k)个连续的虚拟内存页面,并将它们映射到物理内存中任意位置的k个任意的物理页面。由于页表的工作方式,不要求分配连续的个物理内存页面。页面可以随机分布在物理内存中。

image-20200923201426431

9.5虚拟内存作为内存保护的工具

可以在$PTE$中添加许可位来进行访问控制,$SUP$代表是否需要在内核模式下才可以访问该页。

image-20200923201810342

比如进程$i$,在用户模式下,拥有$VP0$的和$VP1$的读写权限,但没有$VP2$的读写权限。

9.6地址翻译

image-20200923203926750

image-20200923204318228

虚拟地址被划分为$VPN$和$VPO$两大部分,其中$TLB$相当于一个页表的缓存,采用多路组相连的形式缓存。通过$VPN$这一部分来索引,其中$VPN$被划分为$TLBI$和$TLBT$这两个部分。

image-20200923204656199

image-20200923204804654

地址翻译一个简单的流程就是虚拟地址去$TLB$中寻找$PPN$,找到之后和$VPO$就组成了物理地址,其中$PPO$等于$VPO$.找到了物理地址之后,将物理地址划分为$CO\ CI\ CT$三部分,再去缓存中寻找对应的数据即可。