这是一个众所周知的事实是Windows应用程序通常有私有地址空间的2Gb 32位系统上。 这个空间可以扩展到用的3Gb / 3GB开关。
4GB的操作系统本身保留剩余。
我的问题是为什么呢?
在内核模式下运行的代码(即设备驱动程序代码)有它自己的地址空间。 为什么,在专属的4Gb地址空间的顶部,操作系统仍然要保留每个用户模式进程的2Gb?
我认为原因是用户模式和内核模式调用之间的过渡。 例如,一个呼叫NtWriteFile
将需要一个地址为内核调度程序(因此为什么系统预留2GB的每个应用程序)。 但是,使用SYSENTER
,是不是系统服务数量足够的内核模式代码知道哪些功能/服务被称为?
如果你能澄清我为什么它如此重要的操作系统采取每个用户模式进程中的2Gb(或1GB)。
Two different user processes have different virtual address spaces. Because the virtual↔physical address mappings are different, the TLB cache is invalidated when switching contexts from one user process to another. This is very expensive, as without the address already cached in the TLB, any memory access will result in a fault and a walk of the PTEs.
Syscalls involve two context switches: user→kernel, and then kernel→user. In order to speed this up, it is common to reserve the top 1GB or 2GB of virtual address space for kernel use. Because the virtual address space does not change across these context switches, no TLB flushes are necessary. This is enabled by a user/supervisor bit in each PTE, which ensures that kernel memory is only accessible while in the kernelspace; userspace has no access even though the page table is the same.
If there were hardware support for two separate TLBs, with one exclusively for kernel use, then this optimization would no longer be useful. However, if you have enough space to dedicate, it's probably more worthwhile to just make one larger TLB.
Linux on x86 once supported a mode known as "4G/4G split". In this mode, userspace has full access to the entire 4GB virtual address space, and the kernel also has a full 4GB virtual address space. The cost, as mentioned above, is that every syscall requires a TLB flush, along with more complex routines to copy data between user and kernel memory. This has been measured to impose up to a 30% performance penalty.
Times have changed since this question was originally asked and answered: 64-bit operating systems are now much more prevalent. In current OSes on x86-64, virtual addresses from 0 to 247-1 (0-128TB) are allowed for user programs while the kernel permanently resides within virtual addresses from 247×(217-1) to 264-1 (or from -247 to -1, if you treat addresses as signed integers).
What happens if you run a 32-bit executable on 64-bit Windows? You would think that all virtual addresses from 0 to 232 (0-4GB) would easily be available, but in order to avoid exposing bugs in existing programs, 32-bit executables are still limited to 0-2GB unless they are recompiled with /LARGEADDRESSAWARE
. For those that are, they get access to 0-4GB. (This is not a new flag; the same applied in 32-bit Windows kernels running with the /3GB
switch, which changed the default 2G/2G user/kernel split to 3G/1G, although of course 3-4GB would still be out of range.)
What sorts of bugs might there be? As an example, suppose you are implementing quicksort and have two pointers, a
and b
pointing at the start and past the end of an array. If you choose the middle as the pivot with (a+b)/2
, it'll work as long as both the addresses are below 2GB, but if they are both above, then the addition will encounter integer overflow and the result will be outside the array. (The correct expression is a+(b-a)/2
.)
As an aside, 32-bit Linux, with its default 3G/1G user/kernel split, has historically run programs with their stack located in the 2-3GB range, so any such programming errors would likely have be flushed out quickly. 64-bit Linux gives 32-bit programs access to 0-4GB.
视窗(像任何OS)比内核+驱动程序多了不少。
您的应用程序依赖于大量的不只是存在于内核空间OS服务。 有很多的缓冲区,拉手可以被映射到你的进程自己的地址空间的各种资源的。 每当你调用返回,说一个Win32 API函数,一个窗口句柄,或刷子,这些东西必须在过程中的某个地方分配。 因此Windows的一部分运行在内核中,是的,其他部分在自己的用户模式进程中运行,而一些人来说,那些应用程序需要直接访问,被映射到您的地址空间。 这部分是难以避免的,但一个重要的附加因素就是性能。 如果每一个 Win32调用所需的上下文切换,这将是一个重大的性能损失。 如果有人能够在用户模式,因为它们所依赖的数据已经映射到你的地址空间来处理,上下文切换,避免了,你救了不少的CPU周期。
因此,任何操作系统需要预留的地址空间中的一些量。 我相信Linux的默认设置只有1GB的操作系统。
之所以MS上2GB解决与Windows已于Raymond Chen的博客曾经解释。 我没有联系了,我不记得细节,但做出的决定,因为Windows NT在Alpha处理器最初的目标,以及,在Alpha的,有一些很好的理由做50/50分裂。 ;)
这是什么做的Alpha的32支持,以及64位代码。 :)
在内核模式下运行(即设备驱动程序代码)的代码,有它自己的地址空间。
不,不是的。 它具有共享的处理的x86处理器的用户模式部分该地址空间。 这就是为什么内核必须在总预留足够的空间和有限的地址空间。
我认为最好的答案是,OS设计者认为,到时候你会关心,人民会使用64位Windows。
但这里有一个更好的讨论 。
部分答案是微处理器架构的历史有关。 下面是一些我所知道的,别人可以提供更多的细节最近。
英特尔8086处理器有一个段偏移架构存储器,给20个的存储器地址,并且为1MB因此总可寻址物理内存。
与其它竞争时代的处理器-如Zilog公司Z80 -英特尔8086有这不得不不仅容纳电子内存只有一个地址空间 ,但这样小的外设键盘,串行端口,打印机端口和视频显示所有输入/输出通信。 (为了比较,Zilog公司Z80曾与专用组件操作码来访问的单独的输入/输出地址空间)
需要允许空间日益增长范围外围扩展导致了原决定段地址空间划分为电子存储器从0-640K,和“其他东西”(输入/输出,ROM,视频存储器等),从640K到1MB。
随着86线增长和发展,并与他们发展个人电脑,类似的方案已被使用,随着4G地址空间的今天2G / 2G分裂结束。