32 位 Windows 7 / Vista 启用 PAE 后仍然不支持 4G 内存原因分析

2009-03-09 19:20:45 旧日重来

2009-12-02:更新 Windows 7 RTM 内核 Patch 地址。

随着内存价格的不断下降,相信很多朋友都和 Aulddays 一样已经用上了 4G 甚至更多的内存。在 64 位 Windows 系统仍存在一些驱动兼容性问题的情况下,32 位的系统仍然是绝对的主流,但 32 位的桌面版 Windows 版系统对 4G 以上内存的支持似乎一直不好。关于这个问题,网上的文章清一色的会提到 PAE(Physical Address Extension 物理地址扩展)技术。遗憾的是,据绝大多数朋友的测试情况来看,即使启用了 PAE,32 位的 Windows Vista 仍然无法使用全部的 4G 内存。在 Vista SP1 中,微软使了个小技巧,让系统属性中可以显示“已安装”的 4G 内存;但更进一步,在任务管理器中证实实际可用的内存仍然只有 3069M(最多不超过 3.25G,依不同配置而定),如下图所示:

32 位 Vista 4G 内存

这一点,在系统属性程序(开始\运行,输入“msinfo32”,回车)中可以更清楚的看出“已安装物理内存”和“可用物理内存”的数量。

PAE?并不足够

PAE 是 32 位系统内存支持不得不说的一个问题。在没有 PAE 的情况下,32 位系统使用 32 位的地址空间,因此总共可以支持 2^32=4G 的内存,再加上一些系统的限制,没有 PAE 的 32 位 Windows 上本来实际只能使用 3G 的内存。而 PAE 则是一种地址扩展技术,通过它可以让操作系统拥有更多的地址空间,理论上可以支持 128G 甚至更多的内存。PAE 在 Windows Server 系统上可以很好的工作,如下图所示,32 位的 Server 2008 (和 Vista 实际使用相同的内核)在开启 PAE 之后可以很好的使用 4G 内存,但 Vista 上即使开启了 PAE 也仍然只能使用 3G 内存(事实上,Vista 默认是开启 DEP 的,而 DEP 功能需要 PAE 支持,因此一般来说 PAE 其实并不需要手动设置而是自动开启的。点击这里可以看到关于 DEP 的详细讨论),这又是为什么呢?

Server 2008 4G 内存

技术大牛 Geoff Chappell 在研究了 Vista 和 Server 2008 的内核之后发现,造成这个限制的实际上是 Vista 的许可证限制!简单来说,vista/2008 内核在启动初期会调用 MxMemoryLicense 未公开 API 函数来确定系统“许可(licensed)”使用的最大内存数量;而 MxMemoryLicense 则会查询 tokens.dat 和 pkeyconfig.xrm-ms 两个文件确定系统的许可证(桌面系统还是服务器系统),接下来再根据许可证类型确定支持内存的最大值。如果系统内存大于根据许可证确定的值,则在内核启动时多余的内存就会被完全忽略掉。这也就是造成 32 位 Vista 不能使用 4G 或以上内存的根本原因。

目前已经有两个测试证实了这个情况,并成功在 32 位 Vista 下使用了 4G 内存。注意:进行这两个测试实际已经违反了 Windows Vista 的使用许可证,所以是存在版权问题的;在弄清这个问题之前请不要轻易进行类似的测试!

测试1. 替换系统授权:

将 Vista 中的 C:\ Windows\ ServiceProfiles\ NetworkService\ AppData\ Roaming\ Microsoft\ SoftwareLicensing\ tokens.dat 文件和 C:\ Windows\ System32\ licensing\ pkeyconfig\ pkeyconfig.xrm-ms 文件分别用 Server 2008 中的同名文件替换。之后再启动系统时内核就会误认为启动的是 Server 2008 系统,而消除 Vista 许可证对内存的限制。但是这样一来很多系统服务和系统组件也会按照 2008 的方式来运行,造成很多不兼容性。

测试2. 修改系统内核

 在 Geoff Chappell 的文章中(点击查看原文)采用了直接 patch 系统内核的方法。经 Aulddays 测试,这种方法同样适用于目前最新版的 Windows 7 RTM 系统这种方法难度较大,但带来的不兼容性则小的多,并且可以完美支持多至 128G 的内存!他的具体做法如下:为避免原始内核被破坏,首先复制系统内核文件 ntkrnlpa.exe,并命名为 ntkr128g.exe,之后的修改都在 ntkr128g.exe 上进行。用 hex 编辑器打开 ntkr128g.exe,查找下列两个字符串:

特征串1:7C 11 8B 45 FC 85 C0 74 0a
特征串2:7C 10 8B 45 FC 85 C0 74 09

两个特征串在内核中都出现且只出现一次,虽然特征串内容不同,但修改方式相同:把 0x8B 开始的 7 个字节(即上面标记为深红色的部分。最前两个字节不作修改!)修改成:

后7个字节修改成:B8 00 00 02 00 90 90

对于目前的两个版本的 Vista 和最新的 Windows 7,修改处的文件偏移地址(即 0x8B 字节的位置)分别如下:

版本号 版本 文件偏移地址
6.0.6000.16386 Windows Vista 0x003040B1, 0x003040F2
6.0.6001.18000 Windows Vista SP1 0x00309AA3, 0x00309AE4
6.1.7600.16385 Windows 7 0x0035C243, 0x0035c283

接下来测试加载修改后的内核。首先需要为修改后的内核重新计算 checksum 和生成数字签名。在命令行中输入下面3个命令:

editbin /release ntkr128g.exe
makecert -r -ss my -n "CN=My Own Testing Authority"
signtool sign -s my -n "My Own Testing Authority" ntkr128g.exe

上述签名过程需要用到三个命令行工具,其中 editbin 在 Visual Studio 中自带,而 makecert 和 signtool 在 Windows SDK 6.0 中自带,如果你机器上安装了 Visual Studio 2008 的话,第一个工具可以在 %VS2008_Dir%\ VC\ Bin\ 中找到,后两个工具可以在 %ProgramFiles%\ Microsoft SDKs\ Windows\ v6.0A\ bin\ 中找到。Visual Studio 2008 Express 和 Windows SDK 6.0 都可以从微软网站免费下载; 如果不想麻烦另外安装的话,也可以点击这里单独下载这几个工具; 如果运行时提示缺少 MSVCR90.DLL,请先点击这里下载安装 VC2008 的运行时组件

最后在系统启动菜单中加入一条新的启动菜单项(需以管理员方式运行命令提示符)(如果是Windows 7 系统的话可将命令中的 Vista 换成 7):

bcdedit /copy {current} /d "Windows Vista With More Than 4GB"

运行成功后,该命令会返回一个 GUID 值,记录下该 GUID 值,并运行下面三条,用之前返回的 GUID 值替换命令中的 guid(命令中包含 guid 的大括号也要输入):

bcdedit /set {guid} pae ForceEnable 
bcdedit /set {guid} kernel ntkr128g.exe 
bcdedit /set {guid} testsigning on

最后,重启系统并在启动菜单中选择 "Windows Vista (或 7) With More Than 4GB" 一项即可。由于修改了内核,系统启动后桌面上会显示“Test Mode”的提示。

查看:原文地址;来源:live.aulddays.com


注意:本站所有文章除特别说明外均为原创,版权所有,转载请务必以超链接方式注明作者出处,并禁止用作商业用途