【发布时间】:2023-03-03 01:11:02
【问题描述】:
我的系统:
物理内存:3GB
Windows XP 服务包 3(32 位)
交换文件大小:30gb
目标:找到我可以在我的机器上分配的最大内存映射大小。
当我运行以下代码分配 2gb 内存映射文件时,调用失败。
handle=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE|SEC_COMMIT,0,INT_MAX,NULL);
对此我一直很困惑,因为我可以通过一次100mb的不断调用CreateFileMapping来分配一个最大为30gb的系统交换文件大小的内存映射文件。
重新启动机器并重新运行向 CreateFileMapping 请求 2gb 内存映射文件的应用程序后,它可以工作并返回一个有效的句柄。所以这让我有点困惑,窗户的引擎盖下到底发生了什么?
所以情况是这样的,我可以创建许多小的内存映射文件,用尽所有系统页面文件(30gb),但是当要求单个分配 2gb 时,调用失败。重新启动机器并运行相同的应用程序时调用成功!
一些注意事项:
1)内存映射文件没有被加载到进程虚拟地址空间,还没有查看文件。
2) 操作系统可以将 100mb 的内存映射文件分配给 30gb 的系统页面文件!
目前我能得出的唯一结论是,Windows XP SP3(32bit)虚拟内存管理器无法成功在系统页面文件中保留请求的2gb,然后由于系统内存碎片而失败(看起来像它需要保留一个连续的内存分配,即使页面文件是每个 4kb)。重新启动后,我假设系统内存碎片较少,因此允许相同的调用成功并分配 2gb 大小的内存映射文件。
我进行了一些实验,在运行机器一天后,我启动了一个小应用程序,它会分配一个 300mb 的内存映射文件,然后释放它。然后它将大小增加 1mb 并重试。最后它停在 700mb 并报告(系统资源不足)。然后我会检查并关闭每个应用程序,这反过来会停止错误消息,它最终会继续分配 3.5gb 大小的内存映射文件!
所以我的问题是这里发生了什么?虚拟内存管理器内部肯定会发生某种类型的内存碎片,因为分配 100mbs 内存映射文件将消耗多达 30gb 的系统页面文件(提交限制)。
更新
结论是,如果您要使用 INVALID_HANDLE_VALUE 创建由系统页面文件支持的大型内存映射文件,那么系统页面文件(交换文件)需要调整到所需大小并处于非碎片状态 大分配> 2gb!尽管在繁重的 IO 负载下它仍然会失败。为了解决所有这些问题,您可以创建自己的具有所需大小的文件(我做了 1tb)并将内存映射到该文件。
最终更新
我在 Windows 7 机器上运行了相同的测试,令我惊讶的是,它每次都能正常工作(直到系统页面文件大小),而无需触及任何东西。所以我猜这只是一个错误,Windows XP 上的大内存分配可能比 Windows 7 更频繁地失败。
【问题讨论】:
-
我能得出的唯一结论是,容纳 2gb 的 4kb 页面文件的表太大,系统内存无法处理,因此它失败了。
-
这是个谜。无论您的虚拟和物理内存有多大,无论您运行多少进程,您都无法在 32 位 Windows 上创建大于 ~300MB 的内存映射文件。