读书笔记-深入操作系统-虚拟内存上

为什么需要虚拟内存

运行一个程序,需要将程序装入内存中,程序中访问的内存地址就是物理地址。而且必须保证程序用到的内存总量小于实际物理机的总量。当运行多个程序的时候,需要为程序分配多个内存
读书笔记-深入操作系统-虚拟内存上_第1张图片
某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存110。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出110M分配给程序B。这种分配方法可以保证程序A和程序B都能运行,但是这种简单的内存分配策略问题很多
存在的问题如下:

  1. 进程地址空间不隔离,A进程可以随意访问B进程的数据,也能随意修改B进程的数据
  2. 内存使用率低,如果又创建了C进程,并且C大于操作系统剩余的8MB内存,此时需要在A,B进程中选择将一个程序暂时拷入磁盘,腾出空间供C使用
  3. 程序运行地址不确定,分配的地址是随机的
虚拟内存

操作系统使用了分页(page)的方式,将系统内存按page的方式分配虚拟内存,一般的操作系统目前每个page是4kb,按这种选择,4GB虚拟地址空间共可以分成1048576个页,512M的物理内存可以分为131072个页。显然虚拟空间的页数要比物理空间的页数多得多。分页的思想是程序运行时用到哪页就为哪页分配内存,没用到的页暂时保留在硬盘上。当用到这些页时再在物理地址空间中为这些页分配内存,然后建立虚拟地址空间中的页和刚分配的物理内存页间的映射。

分页思想的基本理解

下面通过介绍一个可执行文件的装载过程来说明分页机制的实现方法。一个可执行文件(PE文件)其实就是一些编译链接好的数据和指令的集合,它也会被分成很多页,在PE文件执行的过程中,它往内存中装载的单位就是页。当一个PE文件被执行时,操作系统会先为该程序创建一个4GB的进程虚拟地址空间。前面介绍过,虚拟地址空间只是一个中间层而已,它的功能是利用一种映射机制将虚拟地址空间映射到物理地址空间,所以,创建4GB虚拟地址空间其实并不是要真的创建空间,只是要创建那种映射机制所需要的数据结构而已,这种数据结构就是页目和页表。

当创建完虚拟地址空间所需要的数据结构后,进程开始读取PE文件的第一页。在PE文件的第一页包含了PE文件头和段表等信息,进程根据文件头和段表等信息,将PE文件中所有的段一一映射到虚拟地址空间中相应的页(PE文件中的段的长度都是页长的整数倍)。这时PE文件的真正指令和数据还没有被装入内存中,操作系统只是根据PE文件的头部等信息建立了PE文件和进程虚拟地址空间中页的映射关系而已。当CPU要访问程序中用到的某个虚拟地址时,当CPU发现该地址并没有相相关联的物理地址时,CPU认为该虚拟地址所在的页面是个空页面,CPU会认为这是个页错误(Page Fault),CPU也就知道了操作系统还未给该PE页面分配内存,CPU会将控制权交还给操作系统。操作系统于是为该PE页面在物理空间中分配一个页面,然后再将这个物理页面与虚拟空间中的虚拟页面映射起来,然后将控制权再还给进程,进程从刚才发生页错误的位置重新开始执行。由于此时已为PE文件的那个页面分配了内存,所以就不会发生页错误了。随着程序的执行,页错误会不断地产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求。

分页方法的核心思想就是当可执行文件执行到第x页时,就为第x页分配一个内存页y,然后再将这个内存页添加到进程虚拟地址空间的映射表中,这个映射表就相当于一个y=f(x)函数。应用程序通过这个映射表就可以访问到x页关联的y页了

虚拟内存的实现

虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组.每个字节都有唯一的虚拟地址,作为到数组的索引

在任意时间,虚拟页面的集合都分为三个不相交的子集

  1. 未分配的
  2. 缓存的
  3. 未缓存的
    读书笔记-深入操作系统-虚拟内存上_第2张图片
页表(page table)

页面将虚拟页映射到物理页.每次地址翻译硬件将一个虚拟地址转化为物理地址时,都会读取一个页表

读书笔记-深入操作系统-虚拟内存上_第3张图片

图中的PTE((Page Table Entry,PTE)页面标目数组,每个PTE由一个有效位(valid bit)和一个地址组成,有效位表明了该虚拟页当前是否存在于物理内存中,如果有效位是1,该PTE中就会存储物理内存中相应的物理页的起始地址。如果有效位是0,且PTE中的地址为null,这表示这个虚拟页还未被分配,而如果有效位是0且PTE中有地址,那么这个地址指向该虚拟页在磁盘上的起始位置

页命中和页异常

读书笔记-深入操作系统-虚拟内存上_第4张图片

  1. 当读取PTE2,因为设置了有效位,地址翻译就知道pv2是缓存再内存中的,即是页命中
  2. 如果读出PTE3,从内存中取出PTE3,从有效位推断并未被缓存,并且不在内存中,触发一个页异常,缺页异常会调用内核中的缺页异常处理程序,牺牲一个页.如果vp4已经被修改,那么内核将它复制到磁盘。不再缓存到主存中.从磁盘复制VP3到内存PP3,更新PET3,随后返回
局部性原理:如果不命中的话,一直都会触发页异常,页面的调度会相当慢.局部性原理保证了任意时刻,程序将趋向一个较小的集合工作

虚拟内存的作用

  1. 简化链接,独立的进程空间允许每个进程的内存映像使用相同的基本格式,而不用管代码和数据存放在内存的何处
  2. 简化加载,虚拟内存使得更容易向内存中加载可执行文件和共享对象文件
  3. 简化共享
  4. 简化内存分配 为用户进程提供一个简单的分配额外内存的机制.当一个进程需要额外的堆空间时候,操作系统分配一个适当k个连续虚拟内存页面,并且将他们映射到物理内存中的k个任务物理页面

保护机制

通过在PTE上面添加一个额外的标识位来达到保护权限
读书笔记-深入操作系统-虚拟内存上_第5张图片

TLB
  1. MMU: 将虚拟地址翻译为物理地址,由硬件完成

每次MMU必须查阅一个PTE,以便在虚拟地址转化为物理地址.因为在MMU中包含了一个关于PTE的缓存

多级页表

1.类似树的结构,使用多级结构
读书笔记-深入操作系统-虚拟内存上_第6张图片

以上就是虚拟内存的基础知识

参考文章

  1. https://zhuanlan.zhihu.com/p/...
  2. https://www.cnblogs.com/logo-...

参考视频

  1. CMU教授的视频教程 - Lecture17:虚拟内存概念
  2. CMU教授的视频教程 - Lecture18:虚拟内存系统

你可能感兴趣的