::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
来修改首页?
答案 0 :(得分:8)
最直接的答案是假定 是。
尽管文档中没有给出明确担保人,但是可以假定,因为该文件涉及MMU和CPU以及低级内存管理。这与API的其余部分一样起作用:请参见creating guard pages等。总的来说,如果您不能指望精确降低API的所有这些保护功能,它们的实用性将不及实际的一半。导致故障的指令。话虽这么说,但OS / CPU / MMU / TLB / CACHE如何实际完成此工作对我来说还是一片黑暗-如果我弄清楚了,将会更新。
在您的示例中,我会更担心编译器/优化器会在您身上玩弄花样-因此,也许看看生成的程序集,看看实际的写在哪里。
答案 1 :(得分:7)
写监视以页面粒度运行并非偶然。这是因为这是通过MMU的页表在CPU级别处理的。我找不到权威来源,但是我知道这可以通过只读页面属性来实现。被监视的页面是只读的,但是通过将被监视的页面添加到已修改列表中来处理写入时的软页面错误。
因此,处理器高速缓存中的陈旧数据无关紧要。这是在MMU级别处理的,并且MMU始终与高速缓存紧密耦合。
我会更加担心竞争条件,因为这些条件出现在C ++级别。即使GetWriteWatch
正在运行,也可能从另一个线程写入监视的页面。