虚拟内存

  • 虚拟内存是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一大的、一致的和私有的地址空间。通过一个很清晰的机制,虚拟内存提供了三个重要的能力
    1. 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存
    2. 它为每个进程提供了一致的地址空间,从而简化了内存管理
    3. 它保护了每个进程的地址空间不被其他进程破坏
  • 虚拟内存是计算机系统最重要的概念之一
    • 虚拟内存是核心的
      • 虚拟内存遍及计算机系统的所有层面,在硬件异常、汇编器、链接器、加载器、共享对象、文件和进程的设计中扮演着重要角色
    • 虚拟内存是强大的
      • 虚拟内存给予应用强大的能力,可以创建和销毁内存片、将内存片映射到磁盘文件的某个部分,以及与其他进程共享内存。
    • 虚拟内存是危险的
      • 每次应用程序引用一个变量、间接引用一个指针,或者调用一个诸如malloc这样的动态分配程序时,它就会和虚拟内存发生交互

物理和虚拟寻址

  • 物理寻址:计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组。每字节都有一个唯一的物理地址。第一个字节的地址为0,接下来的字节地址为1,再下一个为2,依此类推。给定这种简单的结构,CPU访问内存的最自然的方式就是使用物理地址。
  • 虚拟寻址:使用虚拟寻址,CPU通过生成一个虚拟地址来访问主存,这个虚拟地址在被送到内存之前先转换成适当的物理地址。将一个虚拟地址转换为物理地址的任务叫做地址翻译。就像异常处理一样,地址翻译需要CPU硬件和操作系统之间的紧密合作。CPU芯片上叫做内存管理单元的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容由操作系统管理。

地址空间

  • 地址空间是一个非负整数地址的有序集合:如果地址空间中的整数是连续的,那么说它是一个线性地址空间。在一个带虚拟内存的系统中,CPU从一个有$N=2^n$的地址空间中生成虚拟地址,这个地址空间称为虚拟地址空间
  • 一个系统还有一个物理地址空间,对应于系统中物理内存的M个字节

虚拟内存作为缓存的工具

  • 概念上而言,虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每字节都有一个唯一的虚拟地址,作为到数组的索引。磁盘上数组的内容被缓存在主存中。和存储器层次结构中其他缓存一样,磁盘上的数据被分割成块,这些块作为磁盘和主存之间的传输单元。VM系统通过将虚拟内存分割为称为虚拟页的大小固定的块来处理这个问题。
  • 在任意时刻,虚拟页面的集合都分为三个不相交的子集
    • 未分配的:VM系统还未分配的页,未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间
    • 缓存的:当前已缓存在物理内存中的已分配页
    • 未还缓存的:未缓存在物理内存中的已分配页

页表

  • 同任何缓存一样,虚拟内存系统必须有某种方法来判定一个虚拟页是否缓存在DRAM中的某个地方。
    • 如果是,系统还必须确定这个虚拟页存放在哪个物理页中。
    • 如果不命中,系统必须判断这个虚拟页存放在磁盘的哪个位置,在物理内存中选择一个牺牲页,并将虚拟页从磁盘复制到DRAM中,替换这个牺牲页
  • 这些功能是由软硬件联合提供的,包括操作系统软件、MMU中的地址翻译硬件和一个存放在物理内存中叫做页表的数据结构,页表将虚拟页映射到物理页。每次地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表。
  • 页表是一个页表条目的数组。虚拟地址空间中的每个页在页表中一个固定偏移量处都有一个PTE

页命中

  • 设置了有效位,那么地址翻译硬件就知道二零VP2是缓存在内存中的了。所以他使用了PTE中的物理内存地址,构造出这个字的物理地址

缺页

  • 在虚拟内存的习惯说法中,DRAM缓存不命中称为缺页。

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

  • 虚拟地址仍然是一个有用的机制,因为它大大地简化了内存管理,并提供了一种自然的保护内存的方法
    • 简化链接。独立的地址空间允许每个进程的内存映像使用相同的基本格式,而不管代码和数据实际存放在物理内存的何处。对于64位地址空间,代码段总是从虚拟地址$0×4000000$开始。数据段跟在代码段之后,中间有一段符合要求的对其空白。栈占据用户进程地址空间的部分,并向下生长。这样的一致性大大的简化了链接器的设计和实现,允许链接器生成完全链接的可执行文件,这些可执行文件是独立于物理内存中代码和数据的最终位置的。
    • 简化加载。虚拟内存还使得容易向内存中加载可执行文件和共享对象文件。要把目标问及那中.text.data节加载到一个新创建的进程中,Linux加载器为代码和数据段分配虚拟页,把它们标记为无效的,将页表条目指向目标文件中适当的位置。
    • 简化共享。独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制。
    • 简化内存分配。虚拟内存为用户进程提供一个简单的分配额外内存的机制。

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

  • 任何现代计算机系统必须为操作系统提供手段来控制对内存系统的访问。不应该允许一个用户进程修改它的只读代码段。而且也不应该允许它读或修改任何内核中的代码和数据结构。不应该允许它读或者写其他进程的私有内存,并且不允许它修改任何与其他进程共享的虚拟页面,除非所有的共享这都显式地允许他这么做。
  • 如果一条指令违反了许可条件,那么CPU就触发一个一般保护故障,将故障传递给一个内核中的异常处理程序。Linxu shell一般将这种异常报告为"段错误"。