fork 产生的唯一开销是页表复制和进程 ID 创建

use*_*758 8 linux operating-system kernel fork process

fork() 产生的唯一开销是父页表的复制和为子进程创建唯一的进程描述符。在 Linux 中,fork() 是通过使用 copy-on-write 页实现的。写时复制(或 COW)是一种延迟或完全阻止数据复制的技术。

那么为什么需要复制页表。只要进程以只读模式共享页面或直到他们写一些东西,就不需要复制页表,因为父子进程的翻译是一样的??

有人可以解释..

提前致谢

Mat*_*son 5

因为 COW 是在页面只读的基础上工作的,所以我们需要一份全只读的页表副本。当新进程写入某处时,页面错误被视为写入只读页面的结果。页面错误处理程序查看页面的状态,确定它是否应该被写入(如果不是,段错误,就像你在原始进程中写入只读一样)并将相关的原始页面复制到新的过程。

原始页表对于某些条目是可读写的,因此至少必须复制这些条目。我确实相信整个页表都被复制了(因为它使其他一些代码更简单,并且页表条目不是很大 - 每页四或八个字节[每 4096KB 加上一个条目,每 4009*4096KB 加上一个条目,依此类推]。

还有一些有趣的方面,例如,我们有一些代码可以:

 char *ptr = malloc(big_number);
 // Fill ptr[...] with some data. 
 if(!fork())
 {
      // child process works on ptr data. 
      ...
 }
 else
 {
    free(ptr);
 }
Run Code Online (Sandbox Code Playgroud)

现在,父进程中的页表条目将被删除。如果我们与子进程共享这些,我们需要知道这些页表条目是共享的。

在通过网络接收/发送数据、写入磁盘、换入和换出页面等时,会发生许多其他类似的问题。

  • -1:这不能回答问题。OP 了解 COW 机制,并且页表条目是在 fork 上复制的。问题是为什么必须复制页表条目(真正的答案是它们没有,但实现起来更复杂。它不在 Linux 主线中,我猜是因为复杂性问题)。就像你说的,页表条目可能会在其中一个进程中被删除,Linux 需要保留关于哪些页面被共享的元数据,然后需要进行搜索。这就是复杂性的来源。 (3认同)