mmap():将旧内存重置为零非驻留状态

时间:2014-06-11 20:03:11

标签: linux macos memory-management posix mmap

我正在编写内存分配例程,并且它当前正在顺利运行。我用4096字节页面中的mmap()从操作系统中获取内存。当我启动内存分配器时,我使用mmap()分配1gig的虚拟地址空间,然后在分配时根据我的分配算法的具体情况将其分为多个。

我觉得安心分配多达1gig的内存是因为我知道mmap()实际上并没有将页面放入物理内存,直到我真正写入它们为止。

现在,使用我的分配器的程序可能需要大量内存,并且在这种情况下,操作系统最终必须将整整1g的页面放入物理RAM。问题是该程序可能会进入休眠期,在该期间释放大部分1gig,然后仅使用最少量的内存。然而,我在分配器的MyFree()函数中真正做的就是翻转一些簿记数据,这些数据将以前使用过的gig标记为free,但我知道这并不会导致操作系统删除那些来自物理内存的页面。

我不能使用类似munmap()的东西来解决这个问题,因为分配算法的本质是需要一个连续的内存区域,而不需要任何漏洞。基本上我需要一种方法来告诉操作系统"听,您可以将这些页面从物理内存中删除并将它们清除为0,但是当我再次需要它们时请立即重新映射它们,就好像它们是新鲜的mmap一样( )' d"

最好的方法是什么?

实际上,在写完这一切之后我才意识到我可以做一个munmap(),紧接着是一个新的mmap()。这是正确的方法吗?我觉得这可能是一种更有效的方法。

1 个答案:

答案 0 :(得分:4)

您正在寻找madvise(addr, length, MADV_DONTNEED)。来自the manpage

  

MADV_DONTNEED :不要指望在不久的将来访问。 (目前,应用程序已完成给定范围,因此内核可以释放与其关联的资源。)此范围内页面的后续访问将成功,但将导致从底层映射重新加载内存内容文件(参见mmap(2))或零填充按需页面,用于没有底层文件的映射。

特别注意有关后续访问如何成功但返回零填充需求的语言(对于没有底层文件的映射)。

你的另一个munmap紧随其后的另一个mmap的思维大声的替代方案也会起作用,但会冒内核方面效率低下的风险,因为它不再跟踪单个连续区域的分配;如果有许多这样的unmap-and-remap事件,那么内核数据结构可能会变得非常臃肿。

顺便说一句,使用这种分配器时,使用MAP_NORESERVE进行初始分配非常重要,然后在分配时触摸每个页面,并捕获任何结果SIGSEGV并使其失败分配。 (并且您需要记录您的分配器为SIGSEGV安装处理程序。)如果您不这样做,您的应用程序将无法在已禁用内存过量使用的系统上运行。有关详细信息,请参阅mmap联机帮助页。