给定处理器缓存,Windows中页面写跟踪的可靠性如何

Maa*_*lis 12 c++ windows winapi

是否::GetWriteWatch总是给出修改过的页面的最新列表?还是由于处理器缓存而使某些页面仍被认为是未修改的,因为缓存的写入尚未刷新到主内存?


考虑以下C ++代码片段:

auto ptr = ::VirtualAlloc(NULL, 8192, MEM_COMMIT | MEM_RESERVE, MEM_WRITE_WATCH);
auto num = new (ptr) int{};
::ResetWriteWatch(ptr, 8192);

// ... calculations that involve writing to 'num' ...

::GetWriteWatch(/* ... */);
Run Code Online (Sandbox Code Playgroud)

这将保留并提交两页虚拟内存,修改第一页,最后请求所有已修改的页。

是否可以确保通过调用将首页列出为已修改::GetWriteWatch

dar*_*une 8

假设 答案是肯定的

尽管该文档没有给出明确的保证,但是可以假定它是由于它处理MMU和CPU以及低级内存管理。这与API的其余部分一样起作用:请参阅创建保护页面等。总的来说,如果您不能指望它们精确到导致故障的指令。话虽这么说,OS / CPU / MMU / TLB / CACHE如何实际完成此工作对我来说还是一片黑暗-如果我弄清楚的话,将会更新。

在您的示例中,我会更担心编译器/优化器会对您造成一些麻烦,因此也许可以看看生成的程序集并查看实际的写入位置。


MSa*_*ers 7

写监视以页面粒度运行并非偶然。这是因为这是通过MMU的页表在CPU级别处理的。我找不到权威来源,但是我知道这可以通过只读页面属性来实现。监视页面是只读的,但是通过将监视页面添加到已修改列表中来处理写入时的软页面错误。

这样,处理器高速缓存中的陈旧数据就无关紧要了。这是在MMU级别处理的,并且MMU无论如何都与缓存紧密耦合。

我会更担心竞争条件,因为这些条件出现在C ++级别。即使GetWriteWatch正在运行,也可能从另一个线程写入监视的页面。

  • @MaartenBamelis:具体来说,这是对外部(OS)函数的调用。一个优化的编译器可能会发现在同一程序中调用另一个函数时不必刷新“ num”。 (2认同)