众所周知,Windows 应用程序在 32 位系统上通常有 2Gb 的私有地址空间。使用 /3Gb 开关可以将该空间扩展到 3Gb。

操作系统自行保留剩余的 4Gb。

我的问题是为什么?

在内核模式下运行的代码(即设备驱动程序代码)有自己的地址空间。为什么操作系统除了独享 4Gb 地址空间之外,还要为每个用户模式进程保留 2Gb?

我认为原因是用户模式和内核模式调用之间的转换。例如,调用 NtWriteFile 内核调度例程需要一个地址(因此系统在每个应用程序中保留 2Gb)。但是,使用 SYSENTER, ,系统服务编号不足以让内核模式代码知道正在调用哪个函数/服务吗?

如果您能向我解释一下为什么操作系统占用每个用户模式进程的 2Gb(或 1Gb)空间如此重要。

有帮助吗?

解决方案

两个不同的用户进程有不同的虚拟地址空间。因为virtual↔physical地址映射不同,则从一个用户切换上下文时TLB 缓存无效过程到另一个。这是非常昂贵的,因为没有在TLB已经被缓存的地址,任何内存访问将导致故障和的 PTE

系统调用涉及两个上下文切换:用户→内核,然后内核→用户。为了加快这,是很常见的保留虚拟地址空间的顶部1GB或2GB的内核使用。由于虚拟地址空间并不在这些上下文切换改变,没有TLB刷新是必要的。这是通过在每个PTE用户/管理位,这确保了存储器内核时,才可访问允许而在内核空间;用户空间没有访问即使页表是相同的。

如果有两个独立的TLB的硬件支持,其中一个专供内核使用,那么这种优化将不再是有用的。但是,如果你有足够的空间去奉献,这可能更值得只是做一个更大的TLB。

x86上的Linux曾经支持被称为 “4G / 4G分裂” 的模式。在这种模式下,用户空间的完全访问整个4GB的虚拟地址空间,内核也有一个完整的4GB的虚拟地址空间。成本,如上所述,是每个的系统调用需要一个TLB齐平,与更复杂的例程一起用户和内核存储器之间的数据复制。这已被测量的施加到30%的性能损失。


时代已经改变,因为这个问题最初提出和回答:64位操作系统现在更为普遍。在关于当前x86-64的操作系统,从0到2虚拟地址 47 -1(0-128TB)被允许为用户程序而内核永久地从2驻留的虚拟地址范围内 47 ×(2 17 -1)至2 64 -1(或从-2 47 为-1,如果你把地址作为符号整数)。

如果您运行64位Windows的32位可执行文件,会发生什么?你会认为来自所有虚拟地址0至2 32 (0-4GB)将容易是可用的,但是为了避免暴露在现有方案中的错误,32位可执行仍仅限于0- 2GB,除非它们被重新编译/LARGEADDRESSAWARE。对于那些,他们可以访问0-4GB。 (这不是一个新的标志;与所述/3GB开关,它改变了默认2G / 2G用户/内核分裂到3G / 1G运行32位Windows内核应用相同的,当然,3-4GB仍然会出的范围内。)

什么样的错误的可能有多大?举个例子,假设您正在实现快速排序,有两个指针,ab定点在开始和过去的数组的末尾。如果你选择了中间与(a+b)/2枢轴,它会只要这两个地址都低于2GB的工作,但如果它们都是上面,那么除了会遇到整数溢出,结果将是阵列之外。 (正确的表达是a+(b-a)/2。)

和它们的叠层位于所述2-3GB范围内,因此任何这样的编程错误的一边,32位Linux,使用其默认3G / 1G用户/内核分裂,历来运行程序也很可能被快速冲出。 64位Linux给出32位程序访问0-4GB。

其他提示

视窗(像任何OS)是比内核+驱动多得多。

您的应用程序依赖于大量的不只是存在于内核空间OS服务。 有很多的缓冲区,拉手可以被映射到你的进程自己的地址空间的各种资源的。每当你调用返回,说一个Win32 API函数,一个窗口句柄,或刷子,这些东西必须在过程中的某个地方分配。因此Windows的一部分运行在内核中,是的,其他部分在自己的用户模式进程中运行,而一些人来说,那些应用程序需要直接访问,被映射到您的地址空间。这部分是难以避免的,但一个重要的附加因素就是性能。如果的每一个的Win32调用所需的上下文切换,这将是一个重大的性能损失。如果有人能够在用户模式,因为它们所依赖的数据已经映射到你的地址空间来处理,上下文切换,避免了,你救了不少的CPU周期。

因此,任何需要OS 中设置的地址空间的一些量一边。 我相信Linux的默认设置只有1GB的操作系统。

之所以MS上2GB解决与Windows已于Raymond Chen的博客曾经解释。我没有联系了,我不记得细节,但做出的决定,因为Windows NT在Alpha处理器最初的目标,以及,在Alpha的,有一些很好的理由做50/50分裂。 ;)

这是是与阿尔法对32支持,以及64位的代码。 :)

  

在内核模式下(即,设备驱动程序代码)具有它自己的地址空间中运行的代码。

没有没有。它具有共享的处理的x86处理器的用户模式部分该地址空间。这就是为什么内核必须在总预留足够的空间和有限的地址空间。

我相信最好的答案是,操作系统设计者认为,当您必须关心时,人们将使用 64 位 Windows。

但这里有一个 更好的讨论.

部分答案是与微处理器架构的历史有关。下面是一些我所知道的,别人可以提供更多的细节最近

在英特尔8086处理器具有用于存储一个段偏移结构,给20个的存储器地址,并且为1MB因此总可寻址物理内存。

不同于竞争时代的处理器 - 如Zilog公司Z80 - 英特尔8086只有一个地址空间这不得不不仅容纳电子存储器,但具有这样的微小的外围设备,因为所有的输入/输出通信键盘,串行端口,打印机端口和视频显示器。 (为了比较,Zilog公司Z80曾与专用组件的操作码的单独的输入/输出地址空间访问)

在需要允许日益增长范围导致了原决定段地址空间划分为电子存储器从0-640K,和“其他的东西”周边扩张的空间(输入/输出,ROM,视频存储器等)从640K到1MB。

作为x86的线增长和演进,并与他们演变电脑,类似的方案已被使用,随着4G地址空间的今天的2G / 2G分裂结束。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top