我很好奇为什么 32 位操作系统上的 32 位进程有 2 GB 的限制。根据博客文章聊天问题:32 位和 64 位进程的内存限制,限制可以扩展到3GB,但问题仍然存在。
我看到物理限制是 4 GB,那么 2 或 3 GB 只是 Windows 中的硬编码吗?为什么不像 64 位操作系统上的 32 位进程那样使用 4 GB?
注意:这个问题被标记为重复,但引用的问题指的是 32 位地址空间的 4 GB 限制。这是不是我问的是。我特别想问的是为什么 Windows 会将进程限制为2 GB——即使在 32 位平台上也是如此。接受的答案提到了这一点,但没有解释原因。
答案1
在 NT 平台上,4 GB 虚拟地址空间默认分为两部分,低 2 GB 用于进程地址空间,高 2 GB 供系统使用。
此地址空间是虚拟的,不受 RAM 大小的影响。CPU 和 OS 内存管理器会根据需要将 RAM 的部分映射到虚拟地址空间。这非常复杂,本文不再赘述。这是出于性能、安全性和可靠性方面的考虑而做出的设计决定。
每个进程都有自己的 2 GB 私有地址空间,但只有一个系统地址空间。进程被隔离在自己的私有地址空间中,甚至无法看到其他进程。必要时,可以在两个或多个进程之间共享地址。系统地址空间不对普通进程开放,只有内核级组件(如操作系统本身和设备驱动程序)可以访问。如果一个进程误入歧途,它只会伤害自己;其他进程和操作系统不会受到影响。
但是为什么不给系统自己的私有地址空间,就像进程一样?这样系统和每个进程就可以使用完整的 4 GB 地址空间。这本来可以做到的 - 但存在一个问题。
假设这些都完成了。正在运行的进程将拥有对其自身代码和数据的完全访问权限,一切似乎都很好。但是,如果该进程进行需要访问系统地址空间的 OS 调用(例如 I/O 操作),该怎么办?或者,如果有一个中断需要由内核处理,会发生什么?
CPU 只能看到正在运行的进程的地址空间。该怎么办?解决方案是进行上下文切换,使系统地址空间可见。操作系统可以非常高效地完成此操作,但这确实需要时间。如果需要频繁访问系统地址空间,上下文切换的开销将变得过大,性能会受到影响。
一定有更好的方法。
采用的解决方案是将 4 GB 的总地址空间分成两部分,每部分 2 GB。进程地址空间在较低的 2 GB,系统在较高的 2 GB。这使得系统地址空间始终在范围内,并且可以在需要时随时访问而无需上下文切换。通常情况下,设计决策是出于实际原因而做出的。
2 GB 现在看起来可能非常小而且限制很多,但是在 1993 年 NT 发布时,它是巨大的。并且不要忘记每个进程都有自己的 2 GB。
答案2
根据《Windows Internals》一书,这是一个设计决定。他们将整个 4 GB 虚拟内存空间分为两部分:
- 2 GB 内核模式虚拟地址空间(驱动程序内存窗口等)
- 2 GB 用户模式虚拟地址空间(用户空间程序的内存)
然后是非推荐的/3GB
开关(它将内核从 1 变为 3,并且可能会导致在绝对偏移量处分配的驱动程序出现严重错误),聚丙烯酰胺凝胶电泳并且我相信还有一个 API,当使用时,它允许分配非分页内存并将其动态窗口化到程序地址空间(但抱歉我现在记不起它的名字了)。