unix fork exec序列真的和听起来一样昂贵吗?

bob*_*uba 13 unix fork process exec

我正在阅读forkexec考试,我的书说,无论何时需要在unix系统中运行一个新的(不同的)进程,你都会分叉当前进程,然后是execve.

但是,它还表示无论何时fork调用,父级的整个内存映像都将复制到新进程.

然后我的问题是:如果你的进程有一个非常大的内存映像,你只想运行一个新进程怎么办?如果您要立即替换它,从父进程复制所有数据不是浪费资源吗?

Rog*_*sjö 6

通常fork实际上并不复制所有内存,而是使用"写入时复制",这意味着只要不修改内存,就会使用相同的页面.但是,为了避免以后没有足够的内存(如果进程写入内存)必须分配足够的内存.

这意味着在不允许过度使用内存的系统上从大型进程分叉,内存必须可用.因此,如果您有8 GB的进程分叉,那么至少在短时间内必须有16 GB.

有关其他解决方案,另请参见vfork和posix_spawn.

  • 不幸的是,这个答案是错误的 - 过度使用不是 unix 的一部分,而是某些系统的扩展。最常见的(例如 Linux)在默认情况下不需要完整的 16GB 在 fork 上可用。 (2认同)

Rei*_*ica 5

一些非常古老的系统(早期的unix),或者非常特殊的系统(无mmu的linux)或者非常蹩脚的系统(通过cygwin的windows)确实需要在fork上制作所有页面(“每个字节”)的完整副本,因此潜力就在那里。

现代 UNIX 内核不会复制所有进程内存,而是选择创建虚拟副本。虽然这仅涉及复制的一小部分(需要复制页表),但这仍然可能是许多兆字节并且需要大量时间。

所以答案是,一般来说是的,但大多数现代实现都使用硬件来制作快速虚拟副本,但即使该虚拟副本也不是免费的。

旧系统和一些现代系统都实现了特殊的 vfork() 调用,该调用具有一定的严格限制(尽管不如 vfork 的 POSIX 要求严格),但出于性能原因,请避免此复制。

给出一些实际数字,在我的 GNU/Linux 系统上,我可以每秒从 20MB 进程 fork+exit 1340 次,但在 2000MB 进程上每秒只能 fork+exit 235 次。这两种情况都是vfork+execve更快,这有点不直观,因为很多人认为“fork快”而“execve一定慢”。