由于在32位处理器架构下,对内存的访问限制在4GB以下的空间。为了突破 4GB的限制,现在的32位至强处理器采用一种叫PAE(物理地址扩展)的技术,来实现对超出4GB空间的物理地址的访问。PAE实际上采用了36位的地址总线,这样理论上可以支持64GB内存空间的寻址。

  PAE使得处理器可以支持访问更多的内存空间,但是这还需要操作系统的支持。由于操作系统本身也是32位的,所以需要在操作系统上做相应的处理来支持处理器。Windows系统采用AWE(Address Windowing Extension)来进行处理。具体结构如图2所示。此外,Linux系统在2.4内核以后也支持PAE和超过4GB的内存空间处理。

点击在新窗口中浏览此图片

       32位系统,地址空间是4G。这个没错。用户空间指的是应用程序可以直接访问的地址,系统空间指的是应用程序不能直接访问,必须转到内核模式,由操作系统访问。任何操作系统都分用户空间和系统空间,Unix, Linux都是。
       Windows95, Windows 98, WindowsME系列2G用户空间 + 2G系统空间, 2G的系统空间中含有多个进程共享内存的空间和Win16的程序的代码,这就是Win9x系列容易死机的原因之一。
WinNT, Win2000, WinXP系列2G用户空间 + 2G系统空间.(没有Win9x系列的进程共享内存等等)

那么是不是我启动10个应用,那操作系统占有了10*2G这么多空间?


       首先,要搞清楚内存和地址空间的区别。内存是内存,地址空间是地址空间(太累了,我用memory代替内存,address space代替地址空间吧). 不管你有多少memory,256,还是512M,
32位系统的每个应用都有4G的地址空间(只不过它不能访问上2G罢了).win2000下,你的程序最多可以使用2G空间,并不是说你还就可以分配2G的内存了,一般情况下,内存分配到
一个值是会失败的。比如,你的物理memory = 256M,你的页交换文件大小=256M,那么你分配个516M内存看看,失败!物理内存和页交换文件加起来才512M呢.


       其次,操作系统真的占有了2G的内存吗?也不是。你的程序启动后,操作系统的代码和数据映射到程序的上面2G的空间,只是映射,不是说再启动一个实例放那儿。操作系统要映射一片内存的内容到一个区域是多简单的事情。操作系统一般把系统代码和数据映射到应用程序的上面2G的同一个地方。2个应用程序,它的上面2G空间的代码数据大致上一样(不完全一样,因为还是有些和应用程序相关信息,不过应用程序访问不到,得由系统通过内核态访问).严格说来,下面2G也不是应用程序都能用,0到64K这个空间就不能用,至于为什么,回到DOS时代吧!如果没搞多DOS那就不必要深究了。总之这是故意的。你的指针指到这儿肯定会出错,读都不能读。故意不让你读!

哈哈。

       其实大多数应用程序比如你用VC写个程序,它的入口地址是从4M开始,也就是0x00400000,你看看 yourApp.hInstance的值吧!它就等于0x00400000.越讲越远了,

为什么hInstance是程序的入口地址,跑题了!别扔砖头啊!

那么应用程序怎么申请大于2GB的空间呢?

办法1:就是上面的朋友提过的 通过 /3GB或者/USERVA开关。

boot.ini 里头加上这个开关,系统会让出1G给应用程序访问。系统自己只用1G。这样子不是什么好办法。微软临时的方案而已。应用程序link时加上 LARGEADDRESSAWARE,在生成EXE的时候设置一个标志位,这个位系统看到了就让你访问 3G的空间(但是内存+页交换太小,你分配一样会失败).


/3GB指定3G,/USERVA指定一个值,不是死的3G.

办法2:通过AWE (Address Window Extension),地址窗扩展
窗?是的,窗。你可以人认为是一个buffer,用来作为中间物,给2边的东西倒腾。

socket接受发送数据也有窗的概念,一样的。


       要细看AWE,你到MSDN上查关键是AWE或者Address Window Extension。Google上Goole一把。你有了2G甚至更多的内存(啥机器都有,你不能怀疑一个32位系统装个20G内存会有问题吧?硬件可以做的)可以这么干。没有的话就别这么做了,没什么用.AWE的原理很简单,你在比如4G的物理内存上,分配的一片物理内存X, 你再分配的一片虚拟内存(地址空间)Y,把 X 和 Y 通过address window映射。你可以在这片虚拟内存里头访问4G的物理内存。最多访问多少要看你的参数设置了。


       AllocateUserPhysicalPages分配物理内存, VirtualAlloc申请虚拟内存,MapUserPhysicalPages进行映射。没什么难的.MSDN有个sample做这个事情,看看吧! 这么多关键字了应该好查到了。代码我不贴了 ,占篇幅。


       顺便说一下,内存文件映射并不把什么映射到(2~4G)这范围。它是进程共享数据的方式,并不是扩大内存的方式。不过如果你有个大硬盘,创建这么个映射来保存/修改数据也是可以的,这不要求大的内存。和内存没关系。