::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(/* ... */);
这应该保留并提交两页虚拟内存,修改第一页,最后请求所有修改的页面。
是否可以保证第一页被列出,请通过呼叫::GetWriteWatch
?
钝的答案是假定是。
虽然文档没有给出 explicit guarentee,但可以假定它是因为它处理了MMU和CPU和低级内存管理。这可以作为其余的API:参见创建后卫页面等。总的来说,如果您不能指望它们精确地依赖于它们指示导致故障。话虽如此,OS/CPU/MMU/TLB/CACHE实际上如何实现这一目标有些黑暗至我 - 如果我弄清楚它。
在您的示例中,我会更担心编译器/优化器在您身上播放一些技巧 - 因此,也许会看看生成的汇编,看看实际写作的位置。
在页面粒度上进行写入手表并非偶然。那是因为此操作在CPU级别通过MMU的页面表处理。我找不到权威来源,但我知道这可以通过仅阅读页面属性来工作。手表的页面是只读的,但是通过将手表的页面添加到修改后的列表中时处理写作时的软页故障。
因此,处理器缓存中的陈旧数据无关紧要。这是在MMU级别处理的,并且MMU无论如何都与缓存密切相关。
我会更担心种族条件,因为这些状况出现在C 水平。即使GetWriteWatch
正在运行,也可能会从另一个线程中写入手表页面。