【问题标题】:Checking number of actually allocated pages using anonymous mmap()使用匿名 mmap() 检查实际分配的页数
【发布时间】:2018-09-15 04:28:42
【问题描述】:

我正在使用带有MAP_ANONYMOUS 标志的mmap() 分配一些内存。由于问题的特点,我经常需要将一些数据写入大内存块的一个页面(例如,位于中间),而另一部分保持不变。因此,我不会将大部分未使用的内存进行物理分配。

在我看来,这样的mmap() 调用只是给了我一个指向一些填充为 0 的虚拟页面的指针,但是由于写入时复制和按需分页机制,没有一页(除了第一页)不是实际分配在 RAM 中,直到第一次尝试写入它的内存。

问题是:有一刻我从mmap() 得到了MAP_FAILED(之前有很多成功的调用,分配查询较少),当我试图分配一个大于我的物理RAM 大小的内存块时。所以,看起来实际上分配了更多的页面,即使没有对它们的写访问权限。

我需要你们帮忙解决两个问题,首先: 我对匿名内存分配的看法是否正确,以及(如果不是)有哪些不准确之处?

第二个: 匿名mmap() 完成后,如何测量实际分配的页面数?我试过使用mincore(),结果表明几乎所有页面都“驻留在”内存中(即物理分配的?)。所以,看来mincore() 结果是错误的,或者我完全被卡住了:(

更新。 @Art 提到的内存过度使用似乎确实会影响这一点。但是当我尝试禁用它时(将/proc/sys/vm/overcommit_memory 设置为1 模式或使用mmap()MAP_NORESERVE 标志,我的机器严重冻结,并且硬重置是唯一有帮助的。

【问题讨论】:

    标签: c++ c linux memory mmap


    【解决方案1】:

    “这很复杂。” (警告:我在非 Linux 的 VM 系统方面有更多经验,但多年来我从 Linux 中获得了一些细节)

    通常您的假设是正确的。许多操作系统实际上并没有在mmap 上做很多事情,除了记录“在 V 处分配了 X 页的对象 Y”。访问这些页面会导致页面错误,从而导致实际分配。某些(或全部?)版本的 Linux 将预置零的只读页面映射到此类分配(不确定它是否已更改或是否仍然完成),其余的处理方式类似于写时复制(对我而言)感觉是个坏主意,因为它应该生成更多的 TLB 刷新,以用于读取零内存的可疑优化,这应该很少发生,但我猜 Linux 人已经对其进行了基准测试并发现它很好)。

    有一些注意事项。仅仅因为您不使用 RAM 并不意味着您将被允许过度使用这么多内存。某些 Linux 发行版开始默认设置为不允许过度使用或不允许超过 X% 的过度使用。 Centos/RedHat 就是其中之一(这可能是十年前,我不知道今天的状态)。这意味着即使您只使用 5% 的实际物理内存,如果您创建了 100+X% 的 RAM 的匿名映射,mmap 也会失败。它有一个 sysctl,查一下。它类似于/proc/sys/vm/overcommit_memoryovercommit_ratio 或两者兼而有之,甚至可能更多。

    那么您必须了解资源限制。检查ulimit,如果您被允许创建那么大的映射(ulimit -v),问题可能就这么简单。此外(我不确定 Linux 在这里是如何做到的,但您可以创建简单的测试程序来尝试),数据大小的资源限制 (ulimit -d) 可以视为您可以使用的潜在页面,而不是您当前的实际页面使用(换句话说,在资源限制中没有过度使用)。

    然后让我们回到只在您使用的页面中出错。已经研究了检测访问模式和预测未来故障(以便 mmap:ed 文件可以进行预读),但我不知道它在 Linux 中的状态。感觉将它应用于匿名映射会很愚蠢,但你永远不知道,也许有人正在努力变得聪明。为确保,请在您获得的 mmap:ed 块上使用 madvise(..., MADV_RANDOM)

    终于mincore。我在 Linux 上的经验是它是垃圾,上次我尝试它时它不适用于匿名映射(或者它是私有的?)。在您的情况下,它可能很简单,因为它报告匿名映射的只读写时复制归零页面被认为是“核心”。

    【讨论】:

    • 感谢您的回答!您能否建议一种更可靠的方法来测试哪些页面有问题,哪些没有?我发现了一些系统调用和终端命令(toppspmap ...),但似乎他们无法帮助我检查我对(未)分配页面的假设
    • 我还没有找到可靠的方法。当我需要它时,我发现最好的方法是使用 perf 工具为我计算页面错误。但这仅对调试有用。
    猜你喜欢
    • 2021-12-20
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    相关资源
    最近更新 更多