js84 Asked: 2018-09-16 22:20:15 +0800 CST2018-09-16 22:20:15 +0800 CST 2018-09-16 22:20:15 +0800 CST exec() 之后的 fork() 和 COW 行为 772 我们理解 fork 之后的 COW 行为(如这里所描述的示例)如下:fork 为子进程创建父页表的副本并将物理页标记为只读,因此如果两个进程中的任何一个尝试写入它将触发页面错误并复制页面。 子进程执行后会发生什么?我们假设父进程可以再次写入其页面而不会触发页面错误,但事实证明很难找到有关如何实现的确切信息。 欢迎任何指针(包括代码)! exec fork 1 个回答 Voted Best Answer Kapil Arya 2018-09-18T21:20:19+08:002018-09-18T21:20:19+08:00 当子进程执行时,它的所有当前页面都被替换为一组全新的页面,这些页面对应于新的可执行映像(加上堆、堆栈等)。 现代操作系统通过维护父进程和子进程之间共享的物理页面的引用计数来实现 CoW。如果页面在父子之间共享,则引用计数将为 2。一旦子进程通过 exec,共享页面的引用计数就会递减(例如,它回到 1)因此父进程的任何写操作没有 CoW 也会成功。 为了您的娱乐,创建一个简单的程序,它执行 fork,然后子进程休眠几秒钟,然后执行并执行。现在观察/proc/PID/smapsfork 之前(当然只有父进程)、fork 之后但在 exec 之前和 exec 之后的两个进程的内容。注意 Shared_XXX 页面和相应的地址范围。 在代码方面,有一些简单的 XV6 扩展支持写时复制。一个简单的谷歌搜索可能就足够了。另一个值得关注的地方可能是https://github.com/torvalds/linux/blob/master/kernel/fork.c。从分叉入口开始追踪它并玩得开心。 Fork 相当简单,一旦你掌握了它,但内存管理可能是个婊子。参见“mm/memory.c”:“copy_page_range()”
当子进程执行时,它的所有当前页面都被替换为一组全新的页面,这些页面对应于新的可执行映像(加上堆、堆栈等)。
现代操作系统通过维护父进程和子进程之间共享的物理页面的引用计数来实现 CoW。如果页面在父子之间共享,则引用计数将为 2。一旦子进程通过 exec,共享页面的引用计数就会递减(例如,它回到 1)因此父进程的任何写操作没有 CoW 也会成功。
为了您的娱乐,创建一个简单的程序,它执行 fork,然后子进程休眠几秒钟,然后执行并执行。现在观察
/proc/PID/smaps
fork 之前(当然只有父进程)、fork 之后但在 exec 之前和 exec 之后的两个进程的内容。注意 Shared_XXX 页面和相应的地址范围。在代码方面,有一些简单的 XV6 扩展支持写时复制。一个简单的谷歌搜索可能就足够了。另一个值得关注的地方可能是https://github.com/torvalds/linux/blob/master/kernel/fork.c。从分叉入口开始追踪它并玩得开心。