x64 机器上 x86 LARGEADDRESSAWARE 程序的内核模式内存大小?

Kernel Mode memory size for an x86 LARGEADDRESSAWARE program on an x64 machine?

标题几乎概括了它。我有一个为 x86 平台编译的应用程序,它设置了 /largeaddressaware 标志。 运行 它在 x64 系统上,我“免费”获得扩展的 4GB 用户模式虚拟内存,而无需指定 /3GB 引导选项。在 x86 系统上,这意味着内核模式内存仅为 1GB,但由于 x64 系统可以寻址更多内存,内核模式是否保留 2GB 甚至增加到 3GB?

编辑:明确地说,我想知道 per-process 限制。问题源于阅读 this article.

编辑 2:此问题不是 How much memory can a 32 bit process access on a 64 bit operating system? 的重复问题,因为该问题仅针对 application-accessible 内存,而不是系统可访问内存。如果我误解了并且没有为每个进程的系统保留内存,那么如果有人可以将其写下来作为答案,我将不胜感激。我确定我不是第一个对此感到困惑的人。

有一些误解让您感到困惑。

首先,让我们看一下 32 位 Windows。每个进程的虚拟地址 space 都有一部分分配给进程本身,还有一部分用于内核需要的任何东西。但是,所有进程共享相同的内核内存 - 事实上,您甚至在自己的虚拟地址 space 中拥有内核内存,这基本上是一种性能优化,以避免在处理内核时必须切换地址 spaces应用程序中的对象和数据。

默认情况下,这是一个 1:1 拆分,因此您将获得 2 GiB 的用户地址 space 和 2 GiB 的内核地址 space。这被早期的 32 位 Windows 软件(当您的计算机可能只有 4 MiB 的总内存和 486 CPU 或类似的)使用(ab),因为由于方式内存已布局,您的用户地址 space 从来没有任何指针 超过 2 GiB 障碍 - 有效地为您提供任何指针的最高位,供您自己的数据使用。通常这被用来允许混合 "if it fits, this is a value, otherwise it's a pointer to a structure" 方法,节省内存和一些间接。由于这是如此广泛,默认情况下与早期的拆分相同,以防止出现兼容性问题。但是,您也可以选择加入不同的拆分 - 3 GiB 用户 space 和 1 GiB 内核 space。这就是 /3GB 选项的作用。但这还不够——您的应用程序必须 使用 /LARGEADDRESSAWARE 选择加入。这基本上是说 "I don't do weird stuff with my pointers".

应该注意的是,32 位 OS 或进程并不一定意味着您只能寻址 4 GiB 的内存 - 它只是限制了 CPU 在任何时候可以直接访问的内容.对于内存密集型服务器软件,即使是“32 位”版本也可能支持寻址更多的内存——例如,32 位 MS SQL 服务器通过 AWE 支持高达 64 GiB。这基本上是另一层虚拟化,它允许重新映射虚拟地址的物理地址。理论上,无论有无 AWE,您可以寻址的内存量都没有限制 - 毕竟,没有什么能阻止您拥有自己的硬件作为内存映射文件,有效地为您提供无限地址 space.当然,像分段内存的日子,不太好用也不太实用:)

在 64 位 Windows 上,/3GB 不再有意义并被忽略。默认地址 space 拆分取决于 Windows 的确切版本,但在 "terabytes and more" 范围内,超出了 32 位限制。对于现代 Windows,这通常是 128 TiB 用户 + 128 TiB 内核。 32 位应用程序仍然必须像以前一样使用 /LARGEADDRESSAWARE。但是,由于内核现在是 64 位的,无论如何它都不能与用户进程位于同一地址 space,因此 64 位 OS 上的 32 位应用程序具有完全访问权限到地址 space.

的 4 GiB

当然,这些限制仍然远低于 64 位理论上能够解决的问题。然而,大多数 64 位 CPUs 实际上 不能 寻址整个 64 位地址 space - 我上次检查的最常见的只是 48 -少量。惊喜,惊喜 - 这给了你 256 TiB 的地址 space,Windows 中的限制。毕竟不是微软的阴谋! :) 实际上,这并不是什么新鲜事。 Intel x86 的 32 位 ALU 与 32 位地址 space 相关联的事实在 CPU 历史中是一个非常离群的事实 - CPUs 通常具有较高地址和较低地址 space(对于虚拟寻址或物理寻址)宽度大于它们的 ALU 宽度。 MS DOS 1 MiB 可寻址内存的典型限制(640 kiB 留给用户应用程序)也来自于此 - 当时的“32 位”CPUs 只能使用20 位地址。

如你link的文章所述,32位CPU上可用的4GB地址space分为两部分:用户态或应用程序地址space,内核模式地址space.

用户模式地址space是每个进程的。每个进程在用户模式地址 space 和物理或虚拟内存中的页面之间都有不同的映射。

内核模式地址 space 是相同的,无论哪个进程当前 运行ning。否则,地址 space 必须在每次转换到内核模式时重新映射,这将是非常低效的。 (文章确实这么说,但只是非常简短:"the operating system makes its virtual memory visible in the address space of every process"。)

默认情况下,32 位 Windows 将其平分,2GB 用于用户 space 和 2GB 用于内核 space,但可以配置为将其分为 3GB/改为 1GB。

在 x64 Windows 上,内核 运行s 处于 64 位模式,因此它可以访问 CPU 允许的完整地址 space,这当前是 48 位或 256TB。第一个 x64 Windows 版本仅使用 16TB 地址 space,平分:8TB 用于应用程序地址 space(对于 64 位应用程序)和 8TB 用于内核。在 Windows 8.1 中,这增加到使用 CPU 允许的全部 256TB,再次平均分配:128TB 用于 64 位应用程序,128TB 用于内核。

32 位应用程序 运行 在 WOW64 仿真环境中,CPU 运行ning 在传统模式下。然而,内核永远不会 运行s 在传统模式下。当需要内核转换时,CPU 必须从 legacy 模式切换到 long 模式,这也意味着它从 32 位地址 space 切换到 64 位地址 space. x64 CPUs 的设计使得这种转换是有效的。

因此,32位地址space中的any不需要为内核保留。

为确保向后兼容性,其可执行文件未被标记为大地址感知的 32 位进程仍然限制为 2GB 地址 space。如果可执行文件 大地址感知,进程将获得全部 4GB。

你应该注意到这确实是地址space,而不是内存甚至虚拟内存。 32 位应用程序可以使用文件映射和其他方法来使用超过 4GB 的内存。

您还应该注意 进程 可以访问 2GB/3GB/4GB 地址 space 的事实并不意味着 应用程序 可以使用所有这些space。 Windows 在每个进程中为自己保留一些用户模式地址 space。

地址 space 和其他限制记录在此处:Memory Limits for Windows and Windows Server Releases