UNIX fork执行序列确实听起来像一样昂贵吗?

问题描述 投票:13回答:3

我正在阅读关于forkexec的考试,并且我的书说,每当需要在unix系统中运行新的(不同的)过程时,您都将派生当前过程,然后是execve ]。

但是,它也说,每当调用fork时,父对象的整个内存映像都会复制到新进程中。

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

unix process exec fork
3个回答
6
投票

通常,分叉实际上并不复制所有内存,而是使用“写时复制”,这意味着只要不修改内存,就使用相同的页面。但是,为避免以后没有足够的内存(进程应将其写入内存),必须分配足够的内存。

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

另请参见vfork和posix_spawn,以获取其他解决方案。


3
投票

有些系统非常旧(早期的Unix),或者非常特殊的(无mmu的linux),或者非常笨拙(通过cygwin的Windows)确实需要在fork上制作所有页面的完整副本(“每个字节”),所以潜力就在那里。

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

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

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

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


1
投票

除非有一个进程修改了内存,否则不会进行内存复制,在这种情况下将复制页面;如果在调用fork()之后立即在子进程中调用exec(),则不会进行复制。

实际上,我认为确保在父进程写入内存之前始终调用exec(),子进程始终先运行。

我想您可以在UNIX中的高级编程中找到它。

© www.soinside.com 2019 - 2024. All rights reserved.