c++ - 最大的内存映射分配大小?

标签 c++ memory

我的系统: 物理内存: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 内存映射文件的应用程序后,它可以工作并返回一个有效的句柄。所以这让我有点困惑, window 的引擎盖下到底发生了什么?

所以情况是这样的,我可以创建许多小的内存映射文件,用尽所有系统页面文件(30gb),但是当要求单个分配 2gb 时,调用失败。重新启动机器并运行相同的应用程序时调用成功!

一些注意事项:
1)内存映射文件没有被加载到进程虚拟地址空间,还没有查看文件。
2) 操作系统可以为 30gb 的系统页面文件分配 100mb 的内存映射文件!

目前我能得出的唯一结论是,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 更频繁地失败。

最佳答案

问题是文件碎片。物理内存 (RAM) 与这里的任何内容无关。在虚拟内存系统中,“内存”是从文件系统分配的。物理内存只是对内存访问速度的优化。

当您请求具有写访问权限的内存映射文件时,系统必须有一个具有连续页空闲的文件。系统交换文件通常是零散的。如果您的磁盘驱动器进行了很好的碎片整理,您应该能够使用您选择的文件(而不是系统页面文件)创建一个大型内存映射文件。

因此,如果您确实需要一个 2GB 内存映射文件,则需要在安装时在驱动器上创建一个。这将创建连续 2GB 文件的问题转移到安装上,但是一旦创建,您应该就可以了。

关于c++ - 最大的内存映射分配大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4692426/

相关文章:

objective-c - 创建 NSManagedObject(大尺寸)。内存警告和应用程序崩溃

javascript - 需要部分 JavaScript 文件的内存使用情况

c - C 结构的数据对齐

c++ - `const std::string& s = nullptr` 作为可选参数如何工作

c++ - 如何在重命名函数(c++)中使用变量?

在 QVector 中使用指针和非指针参数的 C++ 模板

assembly - 与 Spectre #2 相比,LFENCE 真的没用吗?

c++ - 什么会导致将指针地址写入 std::cout 崩溃?

c++ - VS2005、VS2008下C++生成的EXE速度; VS2010编译器

c++ - 我如何使用RPM从内存中读取std::string