最近在做个程序,虽然是小型程序,但是使用的内存量却很大,动辄达到10G。在64位系统上可以轻松实现,无奈我是基于32位的系统进行开发,程序还没跑起来就已经被终止了。
试过很多办法,包括文件内存映射等,效率不高,而且由于32位应用程序的限制,可用的内存地址最高只能到0x7FFFFFFF,能调用的内存到2G就是极限了。最后好不容易找到了AWE(Address Windowing Extensions)。
AWE是Windows的内存管理功能的一组扩展,它允许应用程序获取物理内存,然后将非分页内存的视图动态映射到32位地址空间。虽然32位地址空间限制为4GB,但是非分页内存却可以远远大于4GB。这使需要大量内存的应用程序(如大型数据库系统)能使用的内存量远远大于32位地址空间所支持的内存量。
与AWE有关的函数在后面介绍。
为了使用大容量内存,除了要用到AWE外,还有一样东西不能少,那就是PAE(Physical Address Extension)。PAE是基于x86的服务器的一种功能,它使运行Windows Server 2003,Enterprise Edition 和Windows Server 2003,Datacenter Edition 的计算机可以支持 4 GB 以上物理内存。物理地址扩展(PAE)允许将最多64 GB的物理内存用作常规的4 KB页面,并扩展内核能使用的位数以将物理内存地址从 32扩展到36。
一般情况下,windows系统的PAE没有生效,只有开启了PAE后windows系统才可以识别出4G以上的内存。在使用boot.int的系统中,要启动PAE必须在boot.ini中加入/PAE选项。在Windows Vista和Windows7中则必须修改内核文件,同时设置BCD启动项。针对Vista系统和Win7系统可以使用Ready For 4GB这个软件直接完成这一操作,具体方法见Ready For 4GB的软件说明。以下就是一个开启了/PAE选项的boot.ini文件示例:
本文将以Windows 7旗舰版为例介绍如何在打开PAE的情况下使用AWE在程序中达到使用2G以上内存的目的。下图分别为开启PAE和未开启PAE时系统识别出的内存容量区别。
图一.开启PAE
图二.关闭PAE
如果没有打开PAE,系统只能认出3G的内存,最多可以再多0.5G不到,这样即使使用AWE,由于系统和其他应用程序已经占去了一部分内存,剩下的内存或许也只有2G多一点了,没什么太大提高。只有当系统认出了4G以上的内存,AWE才能发挥它真正的作用。
下面我们看看windows中给出的有关AWE的API函数,它们都定义在winbase.h中。
从winbase.h中的定义可以看出,只有当你的系统版本大于或等于0x0500时,才能够使用AWE。各个版本的_WIN32_WINNT值见下表,Windows 2000以下的版本不能使用AWE。
Minimum system required | Minimum value for _WIN32_WINNT and WINVER |
Windows 7 | 0x0601 |
Windows Server 2008 | 0x0600 |
Windows Vista | 0x0600 |
Windows Server 2003 with SP1, Windows XP with SP2 | 0x0502 |
Windows Server 2003, Windows XP | 0x0501 |
Windows 2000 | 0x0500 |
如果你的系统版本符合要求,但是编译器在编译加入了AWE API的代码出错,可以在程序头文件中加入下面的代码。
下面简要介绍一下每个API的功能。
在看实例程序前还有一些设置需要做,需要对系统的本地安全策略进行设置。在win7中,打开“控制面板->系统和安全->管理工具->本地安全策略”,给“锁定内存页”添加当前用户,然后退出,重启(不重启一般无法生效!)。
经过前面的准备(再啰嗦一次:确认自己的电脑装有4G或4G以上的内存;开启PAE,使系统认出4G或以上的内存;设置好本地安全策略),我们就可以通过下面的代码来做个实验了。
代码是从MSDN中AWE的一个Example修改而来的,具体流程见代码中的注释,如果对该Example的源代码有兴趣可以参考MSDN。
程序运行结果如下:
可以看出系统分页的大小为4K,总共申请了655360个分页,也就是2.5G。每个分页成员占4字节,总共2621440字节。2.5G内存分成5段512M的块,成功写入了字符串并成功读取。
在调试过程中,在执行了AllocateUserPhysicalPages函数后设置断点,查看任务管理器,可以看出成功分配了物理内存后,实际物理内存被占用了2.5G,从而验证了AWE的效果。
通过上述示例,我们成功的在32位系统中识别出了4G的内存,并且在32位程序中成功使用了超过2G的内存。借助PAE和AWE,即使在32位系统上,我们也能够顺利开发对内存消耗较大的应用程序,而不需要依赖于64位平台。