fork() 产生的唯一开销是父页表的复制和为子进程创建唯一的进程描述符。在 Linux 中,fork() 是通过使用写时复制页面来实现的。写时复制(或 COW)是一种延迟或完全阻止数据复制的技术。
那么为什么需要复制页表。只要进程以只读模式共享页面,或者直到他们写东西,就不需要复制页表,因为父子进程的翻译是相同的?
有人可以解释一下吗..
提前致谢
fork() 产生的唯一开销是父页表的复制和为子进程创建唯一的进程描述符。在 Linux 中,fork() 是通过使用写时复制页面来实现的。写时复制(或 COW)是一种延迟或完全阻止数据复制的技术。
那么为什么需要复制页表。只要进程以只读模式共享页面,或者直到他们写东西,就不需要复制页表,因为父子进程的翻译是相同的?
有人可以解释一下吗..
提前致谢
因为COW是在页面是只读的基础上工作的,所以我们需要一个全只读的页表副本。当新进程写入某个地方时,页面错误被视为写入只读页面的结果。页面错误处理程序查看页面的状态,确定它是否应该被写入(如果不是,segfault,就像您在原始进程中写入只读一样)并将相关的原始页面复制到新的过程。
对于某些条目,原始页表是可读写的,因此至少必须复制这些条目。我确实相信复制了整个页表(因为它使其他一些代码更简单,并且页表条目不是很大 - 每页四个或八个字节[加上每 4096KB 一个条目,每 4009*4096KB 加上一个条目等向上层级]。
还有一些有趣的方面,例如,如果我们有一些代码:
char *ptr = malloc(big_number);
// Fill ptr[...] with some data.
if(!fork())
{
// child process works on ptr data.
...
}
else
{
free(ptr);
}
现在,父进程中的页表条目将被删除。如果我们与子进程共享这些,我们需要知道这些页表条目是共享的。
在通过网络接收/发送数据、写入磁盘、换入换出页面等时,会出现许多其他类似的问题。