逻辑地址空间大于物理存储和后备存储的总和



当虚拟地址空间大于物理内存时,操作系统可以使用交换来逐出页面帧(例如LRU逐出)。CPU 生成页面错误,然后磁盘中的页面交换到主内存中。当虚拟地址足够大以至于主内存或磁盘都没有足够的存储空间来容纳它时,会发生什么情况?当页面框架也不在磁盘中时会发生什么情况?是否调用了另一个页面错误?

当虚拟地址足够大以至于主内存或磁盘都没有足够的存储空间来容纳它时会发生什么?

虚拟内存系统在辅助存储器中维护逻辑地址空间的映像。设计良好的操作系统不允许进程映射在辅助存储中没有备份的逻辑地址。当应用程序调用系统服务将页映射到逻辑地址空间时,如果没有可用于页的辅助存储,则调用将失败。

当页面框架也不在磁盘中时会发生什么情况?

有一些设计不佳的操作系统可以映射页面,而背后没有辅助存储。调用系统服务来映射页面,即使无法在辅助存储中支持页面,它也会成功。 在这种情况下,您在访问时会收到内存异常(并且在应用程序中没有提示真正的问题为内存分配失败)。

是否调用了另一个页面错误?

不。

在逻辑内存系统(大多数处理器都支持)中,页面有两种状态:

1. Mapped
2. Unmapped

在虚拟内存系统中,有三种状态:

1. Mapped
2. Unmapped and valid
3. Unmapped and invalid

当发生页面错误时,处理器只知道页面未映射到内存。然后,操作系统必须确定页面是否在某处的辅助存储中。如果不是,则操作会导致进程出现异常。如果是,操作系统将加载并映射页面,让该过程继续其快乐的方式。

当虚拟地址空间大于物理内存时,操作系统可以使用交换来逐出页面框架(例如 LRU 逐出)

假设虚拟地址是 48 位(因此一个虚拟地址空间的大小为 256 TiB),并且您正在运行 123 个进程,每个进程都有自己的虚拟地址空间。这总共有 31488 TiB 的虚拟地址空间。注意:对于运行现代操作系统(Windows,Linux等)的现代80x86 PC来说,这是"非常正常的"。

在这 31488 TiB 中:

  • 几乎所有内容都将未使用并标记为"不存在"。如果软件尝试访问它,你会得到一个页面错误,页面错误处理程序意识到这是一个错误,你最终可能会得到一个SIGSEGV(或"蓝屏死机"或......因为它没有被使用,所以操作系统不需要任何 RAM 或任何磁盘空间。

  • 其中一些将是加载到 RAM 中的相同内容,然后映射到许多虚拟地址空间。这对于内核本身和共享库/DLL 来说非常常见。它还包括以下情况:相同的 RAM 用于虚拟文件系统缓存和内存映射文件,或者相同的 RAM 作为"共享内存"映射到 2 个或更多进程,或者当相同的 RAM 映射到 2 个或多个虚拟地址空间作为"写入时复制"(例如,在fork()之后)。

  • 有些将是"写入时分配" - 字面意思是同一页充满零,映射到许多虚拟地址空间中的许多虚拟地址,如果你写入它,你会得到一个页面错误,页面错误处理程序为你尝试写入的页面分配一个新的 RAM 页面。这允许操作系统假装分配了大量的虚拟空间并用零填充,而无需使用任何 RAM 或任何磁盘空间(直到实际修改

    )。
  • 有些将是特定流程独有的(修改的)数据。

最终结果是,31488 TiB 的总虚拟空间可能只需要几 GiB 的 RAM(并且可能根本不会使用交换空间)。

过度投入

操作系统做了一堆技巧来假装内存被分配,而实际上并没有。这可能会导致最坏的情况,即操作系统假装分配的所有内存实际上都需要分配。有两种方法可以解决这个问题:

a) 如果您无法涵盖最坏的情况,则拒绝让进程分配更多(例如,当进程尝试分配的内存超过操作系统可以提供的内存时,返回"内存不足"错误)。这很糟糕,因为最坏的情况极不可能,你最终会无缘无故地软件失败("没有足够的内存",而实际上有足够的内存来满足当前的需求)。

b) 允许进程分配更多(在合理范围内),即使你不能覆盖最坏的情况。这在大多数情况下都工作正常,但如果最坏的情况真的发生了,则必须中断某些内容(例如,操作系统终止进程以释放一些RAM)。

最好的选择(在我看来)是第一个选项(不允许过度提交),但要有大量的交换空间。本质上;这就像"允许过度提交 RAM,但不允许过度提交交换空间 + RAM";操作系统可能会在必须开始告诉进程"没有更多内存"之前运行缓慢(由于过度使用交换空间);并且大多数时候一切都在 RAM 中(理想情况下,交换空间仅用于覆盖不太可能的最坏情况)。

最新更新