操作系统为每个进程提供了一个独立的页表,即一个独立的虚拟地址空间。

站在内存管理的角度观察虚拟内存,我们能得到这些结论:

  1. 虚拟内存简化了Linking的过程。由于虚拟内存这个抽象层,以Linux系统内存布局为例,永远是代码段、数据段从低向高布局,用户栈由高向低生长,代码段起始地址为0x400000。Linux下的链接程序只要依照这个规则布局内存,而不用关心虚拟内存之下,物理内存地址的布局。这种抽象大大简化了链接器的设计、实现。
  2. 虚拟内存简化了加载的过程。在虚拟内存的抽象下,加载器从不需要从磁盘到内存进行实际的数据复制。加载器需要为代码段、数据段分配虚拟页,把它们的有效位设为0(即此时还未被主存缓存),把也地址字段指向磁盘中对应的位置。
    (补充:每个页初次被引用存在两种情况:CPU取指;一条正在执行的指令引用一个内存位置。)
  3. 虚拟内存简化了共享的过程。以C为例,许多C程序都会调用一些如printf的标准库函数。虚拟内存抽象允许操作系统将不同进程不同的虚页映射到相同的物理页面,从而安排多个进程共享这部分物理页面存放的代码。
  4. 简化内存分配。以malloc为例,malloc只需要保证分配的虚拟内存页是连续的。而虚拟内存页被映射到的物理页并不存在连续的要求。

站在内存保护的角度观察虚拟内存,能得到如下结论:

通过向页表条目添加更多的许可位,即可实现对内存的访问控制。书中提到一个增加许可位的示例:增加一个sup位,表示进程是否要运行在内核模式下才能访问该条目;增加read、write位,表示该进程是否有权限读/写该页表条目。

如果一条指令违反了这些许可条件,则CPU触发一个一般保护故障,将控制流传递给OS内核中的异常处理程序。