首页 > 编程笔记 > 操作系统笔记

什么是虚拟内存,虚拟内存及其作用详解

前面介绍了计算机系统的各种内存管理策略,例如分页分段等,所有这些策略都有相同的目标,就是同时将多个进程保存在内存中,以便允许多道程序。然而,这些策略都倾向于要求每个进程在执行之前应完全处于内存中。

虚拟内存技术允许执行进程不必完全处于内存。这种方案的一个主要优点就是,程序可以大于物理内存。此外,虚拟内存将内存抽象成一个巨大的、统一的存储数组,进而实现了用户看到的逻辑内存与物理内存的分离。这种技术使得程序员不再担忧内存容量的限制。

虚拟内存还允许进程轻松共享文件和实现共享内存。此外,它为创建进程提供了有效的机制。然而,虚拟内存的实现并不容易,并且使用不当还可能会大大降低性能。

说了这么多,到底什么是虚拟内存呢?

内存管理算法的实现有一个基本要求,就是执行的指令应处于物理内存中。满足这一要求的第一种方法是,将整个逻辑地址空间置于物理内存中。动态加载可以帮助缓解这种限制,但它通常需要特殊的预防措施和程序员的额外工作。

指令应处于物理内存以便执行的要求,似乎是必要的和合理的,但它也是有缺点的,因为它将程序的大小限制为物理内存的大小。事实上,通过实际程序的研究会发现,在许多情况下并不需要将整个程序置于内存中。

例如,分析以下内容:
即使在需要整个程序的情况下,也可能并不同时需要整个程序。分段能够执行只有部分处于内存的程序,可以带来许多好处:
虚拟内存将用户逻辑内存与物理内存分开。这在现有物理内存有限的情况下,为程序员提供了巨大的虚拟内存(如图 1 所示)。

虚拟内存大于物理内存的图例
图 1 虚拟内存大于物理内存的图例

因此,虚拟内存使得编程更加容易,因为程序员不再需要担心有限的物理内存空间,只需要关注所要解决的问题。

进程的虚拟地址空间就是进程如何在内存中存放的逻辑(或虚拟)视图。通常,进程从某一逻辑地址(如地址 0)开始,连续存放,如图 2 所示。

虚拟地址空间
图 2 虚拟地址空间

注意,在图 2 中,随着动态内存的分配,允许堆向上生长。类似地,随着子程序的 不断调用,还允许堆栈向下生长。堆与堆栈之间的巨大空白空间(或空洞)为虚拟地址的一部分,只有在堆与堆栈生长时,才需要实际的物理页。包括空白的虚拟地址空间称为稀疏地址空间。采用稀疏地址空间的优点是随着程序的执行,堆栈或堆会生长或需要加载动态链接库(或共享对象),此时可以填充这些空白。

前面讲过,物理地址可以按帧来组织,并且分配给进程的物理帧也可以不连续。这就需要内存管理单元(MMU)将逻辑页映射到内存的物理页帧。

采用虚拟内存的共享库
图 3 采用虚拟内存的共享库

除了将逻辑内存与物理内存分开外,虚拟内存允许文件和内存通过共享页而为多个进程所共享。这带来了以下好处:
  1. 通过将共享对象映射到虚拟地址空间中,系统库可以为多个进程所共享。尽管每个进程都将库视为其虚拟地址空间的一部分,但是驻留在物理内存中的库的实际页可由所有进程共享(图 3)。通常,库按只读方式映射到与其链接的进程空间。
  2. 类似地,虚拟内存允许进程共享内存。进程之间可以通过使用共享内存来进行通信。虚拟内存允许一个进程创建一个内存区域,以便与其他进程共享。共享这个内存区域的进程认为,它是其虚拟地址空间的一部分,而事实上这部分是共享的,如图 3 所示。
  3. 当通过系统调用 fork() 创建进程时,可以共享页面,从而加快进程创建。

所有教程

优秀文章