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

New Windows 8.1 APIs for virtual memory management: `DiscardVirtualMemory()` vs `VirtualAlloc()` and `MEM_RESET` and `MEM_RESET_UNDO`

Windows 8.1/Server 2012RC2 刚刚为虚拟内存管理引入了新的 APIs:OfferVirtualMemory()ReclaimVirtualMemory()DiscardVirtualMemory(),它们的用法是很简单,只要看看他们的名字就可以了。

我无法理解这些 API 与 VirtualAlloc() 以及标志 MEM_RESETMEM_RESET_UNDO 的工作原理,以及它们之间的细微差别。

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

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

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

现在,让我们看看 DiscardVirtualMemory():这里 MSDN 没有提到 MEM_RESET 标志,但是如果我阅读这个 API 的描述,似乎 真的VirtualAlloc()+MEM_RESET.

相同

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

如果我想从 POSIX 移植一个应用程序,它使用 madvise(2)MADV_DONTNEEDMADV_WILLNEED,模仿这个 [=62= 的最佳方法是什么] 行为?到目前为止,我对 MADV_DONTNEED 使用 VirtualAlloc()+MEM_RESET,对 MADV_WILLNEED 使用 VirtualAlloc()+MEM_RESET_UNDO。可以吗,或者我可以用那些新的 APIs 做得更好?

DiscardVirtualMemory on MSDN

When the region of memory is again accessed by the application, the backing RAM is restored, and the contents of the memory is undefined.

如果我从字里行间看出,

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

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

这使得 windows 可以减少对归零页面池的压力,当程序想要更好时,并告诉 windows 它可以丢弃一些释放的内存范围.