【问题标题】:largest memory map allocation size?最大的内存映射分配大小?
【发布时间】: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 的内存映射文件。

标签: c++ memory


【解决方案1】:

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

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

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

【讨论】:

  • 整理系统页面文件告诉你怎么回事
  • 成功创建:22,743mb的映射
  • 提问者。在繁重的 IO 负载或操作系统的正常使用下,我的分配可以从 20gb 下降到只有 6gb,有时甚至下降到 300mb。我的假设是 Windows 虚拟内存管理器已将页面放在系统页面文件中,从而破坏了它找到空闲页面的能力。虽然在运行繁重的 IO 程序后等待了 30 分钟,但我可以再次重新分配 20gb。任何想法发生了什么?我猜 Windows 需要时间来卸载这些页面。
  • 记住系统页面文件代表了所有的虚拟内存。当您调用 malloc 并增长堆时,您正在分配系统文件中的页面。即使物理内存可用于分配,也必须为其分配页面文件中的支持页面。操作系统不断运行不断分配和释放内存的程序。最终事情可能会“平静下来”,分配的内存(由页面支持)将会减少......
  • ... VMM 是否像垃圾收集器对堆进行碎片整理一样对页面文件进行碎片整理?或者您是否遇到巧合,所有最近的活动都发生在连续的页面中?我不知道。
【解决方案2】:

所以我的问题是这里发生了什么?虚拟内存管理器内部肯定会发生某种类型的内存碎片,因为分配 100mbs 内存映射文件将消耗多达 30gb 的系统页面文件(提交限制)。

听起来差不多。如果您不需要大的连续内存块,请不要要求它们是否可以在较小的块中获得相同数量的内存。

为了找到我可以在我的机器上分配的最大内存映射大小。

  • 试试 X 码。
  • 如果失败,请尝试使用大小 X/2 并重复。

这会在运行时为您提供一个块,可能不是最大可能的块,但在 2 倍以内。

【讨论】:

  • 我的第一个想法是虚拟地址空间碎片。然而,这不应该在这里发挥作用,因为还没有涉及虚拟地址 - 只有在您映射视图后才会分配这些地址。它还可能是什么其他碎片?
  • 是的,这是一种有效的方法,但我更好奇为什么看到它会保留在系统页面文件中导致调用失败的原因是什么?是不是因为系统内存碎片。我能得出的唯一结论是,容纳 2gb 的 4kb 页面文件的表太大,系统内存无法处理,因此它失败了。
【解决方案3】:

让我们担任 Windows 开发人员的职位。 假设一些用户执行以下步骤:

  1. 创建内存映射。
  2. 用敏感数据填充一些内存
  3. 从文件中取消映射
  4. 继续使用内存
  5. Windows 需要为关键任务卸载这些页面。

解决方案 - 映射内存应该适合交换。但这并不意味着映射将被交换。

【讨论】:

    猜你喜欢
    • 2018-11-15
    • 2011-11-15
    • 2022-11-02
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    相关资源
    最近更新 更多