我正在阅读关于fork
和exec
的考试,而我的书中说,无论何时需要在unix系统中运行新的(不同的)流程,您都会分叉当前的流程然后是execve
。
但是,它还说每当调用fork
时,父项的整个内存映像都会复制到新进程。
然后我的问题是:如果你的进程有一个非常大的内存映像,你只想运行一个新进程怎么办?如果您要立即替换它,那么从父进程复制所有数据不是浪费资源吗?
答案 0 :(得分:6)
通常fork实际上并不复制所有内存,而是使用“写入时复制”,这意味着只要不修改内存,就会使用相同的页面。但是,为了避免以后没有足够的内存(如果进程写入内存)必须分配足够的内存。
这意味着在不允许过度使用内存的系统上从大型进程分叉,内存必须可用。因此,如果您有8 GB的进程分叉,那么至少在短时间内必须有16 GB。
另请参阅vfork和posix_spawn以获取其他解决方案。
答案 1 :(得分:2)
有些系统要么非常陈旧(早期unix),要么非常特殊(mmu-less linux)或verfy crappy(windows通过cygwin)确实需要在fork上制作所有页面的完整副本(“每个字节”) ,所以潜力就在那里。
现代unix内核不会复制所有进程内存,而是选择制作虚拟副本。虽然这只涉及一小部分复制(页面表需要复制),但这仍然可能是几兆字节并且需要相当长的时间。
所以答案是肯定的,但大多数现代实现都使用硬件来制作快速虚拟副本,但即使是虚拟副本也不是免费的。
旧的和一些现代系统都实现了一个特殊的vfork()调用,它有一些严格的限制(虽然不如VIX的POSIX请求那么严格),但出于性能原因,请避免使用此副本。
为了给出一些实际的数字,在我的GNU / Linux系统上,我可以从20MB进程中每秒退出1340次,但在2000MB进程上只有235次/秒。在这两种情况下,vfork + execve都会更快,这有点不直观,因为很多人认为“fork很快”,“execve必须慢”。
答案 2 :(得分:1)
除非其中一个进程修改了内存,否则不会进行内存复制,在这种情况下页面将被复制,如果在调用fork()之后正在子进程中调用exec(),则不会进行复制
实际上我认为要确保在父进程写入内存之前总是调用exec(),子进程总是先运行。
我认为您可以在 UNIX中的高级编程
中找到它