虚拟内存

虚拟内存作为缓存的工具

虚拟内存被组织为一个由存放在磁盘上的 N个连续的字节大小的单元组成的数组。每字节都有一个唯一的虚拟地址,作为到数组的索引。磁盘上数组的内容被缓存在主存中。和存储器层次结构中其他缓存一样 ,磁盘(较低层) 上的数据被分割成块,这些块作为磁盘和主存(较高层) 之间的传输单元。在虚拟内存系统中,这个块被称为页面。
VM 系统将虚拟内存分割为称为虚拟页(Virtual Page, VP)的大小固定的块。物理内存被分割为 物理页(Physical Page, PP)(物理页也被称为页帧(page frame))。物理页与虚拟页大小相同。物理页用来缓存虚拟页。术语 DRAM 缓存来表示虚拟内存系统的缓存,它在主存中缓存虚拟页。 DRAM 缓存是全相联的,即任何虚拟页都可以放置在任何的物理页中。
在任意时刻,虚拟页面的集合都分为三个不相交的子集:

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

页表

页表(page table)是一个存放在物理内存中的数据结构,页表将虚拟页映射到物理页。每次MMU将一个虚拟地址转换为物理地址时,都会读取页表。操作系统负责维护页表的内容, 以及在磁盘与 DRAM 之间来回传送页。
页表就是一个页表条目(Page Table Entry, PTE)的数组。虚拟地址空间中的每个虚拟页在页表中一个固定偏移量处都有一个 PTE. 一个 PTE代表一个虚拟页,其索引也是虚拟页的索引,PTE是由一个 有效位(valid bit)和一个 n 位地址字段组成的。 有效位表明了该虚拟页当前是否被缓存在 DRAM 中。如果有效位设置为1,那么地址字段就表示DRAM中相应物理页的起始地址,这个物理页缓存了该虚拟页。如果有效位设置为0,那么当地址字段是空地址时表示该虚拟页还未分配,否则该地址是在磁盘中该虚拟页的起始位置(未缓存的虚拟页)。

分配页面

当内核在磁盘上分配一个新的虚拟页时,将在磁盘上创建空间并更新相应的页表条目,使其指向磁盘上新创建虚拟页的起始地址。

缺页

DRAM 缓存不命中称为缺页(page fault)。当有不命中发生时,才换入页面的这种策略称为按需页 面调度(demand paging)。在磁盘和内存之间传送页的活动叫做交换(swapping)或者页 面调度(paging)。 页从磁盘换入(或者页面调入) DRAM 和从DRAM 换出(或者页面调出)磁盘。
换入时,内核从磁盘拷贝 虚拟页 到内存中的 物理页, 更新虚拟页对应的页表条目,将有效位设置为1,地址字段设置为物理页的起始地址。
换出时,更新被换出的虚拟页的页表条目,将有效位设置为0,如果被换出的虚拟页被修改了,内核将其拷贝回磁盘,如果没有被修改,就直接将地址字段设置为在磁盘上该虚拟页的起始地址。

虚拟内存与时间局部性

局部性原则保证了在任意时刻,程序将趋向于在一个较小的活动页面(active page)集合上工作,这个集合叫做工作集(working set)或者常驻集合(resident set)。 在初始开销,也就是将工作集页面调度到内存中之后,接下来对这个工作集的引用将导致命中,而不会产生额外的磁盘流量。

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

操作系统为每个进程提供了一个独立的页表, 因而也就是一个独立的虚拟地址空间。VM 简化了链接和加载、代码和数据共享, 以及应用程序的内存分配。

简化链接

独立的地址空间允许每个进程的内存映像使用相同的基本格式, 而不管代码和数据实际存放在物理内存的何处。这样的一致性极大地简化了链接器的设计和实现,允许链接器生成完全链接的可执行文件,这些可执行文件中的代码和数据的最终位置是独立于物理内存的。

简化加载

要把目标文件中 .text 和 .data 节加载到一个新创建的进程中, Linux 加载器为代码和数据段分配虚拟页, 把它们标记为无效的( 即未被缓存的), 将页表条目指向目标文件中适当的位置。有趣的是,加载器不从磁盘实际复制任何数据到内存。在每个页初次被引用时, 要么是 CPU 取指令时引用的, 要么是一条正在执行的指令引用一个内存位置时引用的,虚拟内存系统会按照需要自动地换入虚拟页。
将一组连续的虚拟页映射到任意一个文件中的任意位置的表示法称作内存映射(memory mapping)。 Linux 提供一个称为 mmap 的系统调用, 允许应用程序自己做内存映射。

简化共享

每个进程必须调用相同的操作系统内核代码,而每个 C 程序都会调用 C 标准库中的代码,比如 printf。操作系统通过将不同进程中适当的虚拟页面映射到相同的物理页面,从而安排多个进程共享这部分代码的一个副本,而不是在每个进程中都包括单独的内核和 C 标准库的副本。

简化内存分配

当一个运行在用户进程中的程序要求额外的堆空间时( 如调用 malloc 的结果),假设操作系统分配 k个连续的虚拟内存页面, 并且将它们映射到物理内存中任意位置的k个任意的物理页面。由于页表工作的方式,操作系统没有必要分配k个连续的物理内存页面。页面可以随机地分散在物理内存中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值