叉子后COW如何工作?

时间:2016-09-28 14:36:11

标签: unix memory-management fork copy-on-write

在现代类UNIX系统中执行fork后,我正在阅读有关使用 COW -approach的内容。

假设我们有进程 - P1。它分叉;我们得到另一个过程 - P2。 由于 COW ,它们的虚拟内存由相同的物理页面支持。 有一个页面,其中一个静态全局变量(例如,static long variable;之外的main)位于( .data 段)中,由物理页面A支持。

现在P1改变了它的静态全局变量;内核在处理保护错误后,将新页面(页面B)映射到P1的虚拟内存以存储该更改的变量。

P2改变其静态全局变量的方式相同,内核在处理保护错误后,将新页面(页面C)映射到P1的虚拟内存以存储更改的变量。

现在没有任何内容引用页面A. 它在哪里?我想它不是悬在空中"保持一个物理页面不被使用,从而浪费内存?

2 个答案:

答案 0 :(得分:2)

创建页面B时,页面A上的COW标志被删除,因为页面不再共享;在修改它之前不再需要复制它。因此,P2只使用页面A,可能根本不会发生页面错误,当然也不需要复制页面。因此,没有页面C,页面A不会被未引用。

请注意,如果P1在修改页面A上的变量之前再次分叉,或者P2分叉,或两者兼有,则可能有3个或更多进程引用该页面。系统通常为存储器映射控制信息中的每个页面维护一个引用计数器,记录将页面映射到其进程存储器的进程数,并且该计数控制是否可以清除COW标志。在只有一个进程引用页面之前,COW标志仍然有效。

exec操作将减少旧进程中所有页面的引用计数,如果引用计数变为零,则将释放页面以供重用。如果P1设置了一些显式共享内存,则即使引用计数器可能大于1,共享内存页也不会设置COW标志。

答案 1 :(得分:1)

页面A不会悬空,因为只有一个副本发生。 其中一个过程将首先触发COW。它将获得新的框架B,而另一个过程坚持使用A. 我们可以安排其他进程不会出现页面错误。这可能充满了种族,特别是在SMP下,每个核心都有自己的TLB。 或者我们也可以让其他进程出现页面错误。它将知道帧A不再需要复制,因为例如在管理对象中存在跟踪A的引用计数,并且该引用计数具有值1,指示A被唯一地映射。所以页面错误处理程序只会将页面标记为存在,使其保持映射到A. 如果父母产生一个孩子,该孩子退出,然后父母触摸先前共享的页面,则应该发生同样的事情。由于它不再共享,因此没有理由进行复制写入。