软脏PTEs

软脏位是PTE上的一个位,用于跟踪任务写入了哪些页面。为了进行此跟踪,需要

  1. 清除任务PTEs中的软脏位。

    这通过向目标任务的/proc/PID/clear_refs文件写入“4”来完成。

  2. 等待一段时间。

  3. 从PTEs中读取软脏位。

    这通过从/proc/PID/pagemap读取来完成。64位四字中的第55位是软脏位。如果设置,则自步骤1以来相应的PTE已被写入。

在内部,为了进行此跟踪,当软脏位被清除时,PTEs中的可写位也会被清除。因此,在此之后,当任务尝试修改某个虚拟地址的页面时,会发生#PF(页错误),内核会在相应的PTE上设置软脏位。

请注意,尽管在清除软脏位后,任务的所有地址空间都被标记为只读(r/o),但在此之后发生的#PF(页错误)处理速度很快。这是因为页面仍然映射到物理内存,因此内核所做的只是发现这一事实,并在PTE上同时设置可写位和软脏位。

虽然在大多数情况下,通过#PF(页错误)来跟踪内存变化已经足够,但仍然存在一种可能丢失软脏位的情况——一个任务取消映射之前已映射的内存区域,然后在完全相同的位置映射一个新的区域。当调用unmap时,内核会内部清除PTE值,包括软脏位。为了通知用户空间应用程序此类内存区域的更新,内核总是将新的内存区域(和扩展的区域)标记为软脏。

此功能被检查点-恢复项目积极使用。您可以在http://criu.org找到更多详细信息。

-- Pavel Emelyanov,2013年4月9日