用于虚拟内存管理的新 Windows 8.1 API:“DiscardVirtualMemory()”与“VirtualAlloc()”以及“MEM_RESET”和“MEM_RESET_UNDO”

Mar*_*cci 7 winapi posix memory-management virtual-memory windows-8.1

Windows 8.1/Server 2012RC2 刚刚引入了用于虚拟内存管理的新 API:OfferVirtualMemory()ReclaimVirtualMemory()DiscardVirtualMemory(),它们的用法非常简单,只需查看它们的名称即可。

我不明白的是这些 API 如何与VirtualAlloc()标志MEM_RESET和一起工作MEM_RESET_UNDO,以及有哪些细微的区别。

对于OfferVirtualMemory(),MSDN 表示它与VirtualAlloc()+非常相似MEM_RESET,只不过它从工作集中删除页面,并限制对页面的进一步访问。

因此,基本上它限制了对页面的访问,如果我想再次访问这些页面,我必须调用ReclaimVirtualMemory(). 这很好,但不应该MEM_RESET也从工作集中删除页面吗?不应该MEM_RESET充当 POSIXMADV_DONTNEED标志,madvise(2)它基本上从进程的页表中删除页面,如果我将来再次访问这些页面,访问将生成软故障,并且这些页面将再次重新分配,初始化为零。

当然,如果这是真的,页面将从进程的工作集中删除,因为它们基本上被释放,即使进程保留分配的虚拟地址,并看到它们“已提交”。

现在,让我们看看DiscardVirtualMemory():这里 MSDN 没有提到任何关于MEM_RESETflag 的内容,但是如果我阅读了这个 API 的描述,它似乎与+确实是一样的。VirtualAlloc()MEM_RESET

那么,有谁知道这些 API 之间是否存在一些差异,以及这些细微差异的正确用例是什么?如果他们引入了像 一样的全新 API DiscardVirtualMemory(),那么与旧方法应该会有一些区别。

如果我想从 POSIX 移植一个使用madvise(2)和 的MADV_DONTNEED应用程序MADV_WILLNEED,模仿这种 POSIX 行为的最佳方法是什么?到目前为止,我使用VirtualAlloc()+ MEM_RESETforMADV_DONTNEEDVirtualAlloc()+ MEM_RESET_UNDOfor MADV_WILLNEED。可以吗?或者我可以使用这些新 API 做得更好吗?

dou*_*536 3

MSDN 上的丢弃虚拟内存

当应用程序再次访问该内存区域时,后备 RAM 会恢复,并且内存的内容未定义。

如果我从字里行间读到,那就是:

  • 当您访问它时,其中的一些内容可能仍然存在
  • 当这些页面提交时,它可以给你垃圾初始化的页面
  • 如果机器实际上受到内存限制,某些页面有时可能会被零初始化

如果您使用旧版 API 重置虚拟地址范围,则不会发生这种情况。在这种情况下,当您稍后访问这些页面时,可以保证提供零初始化页面。

当程序想要变得更加友好时,这使得窗口可以减少对清零页面池的压力,并告诉窗口它可以丢弃一些已释放的内存范围。