Ell*_*tus 51 process process-management fork
用于进程创建的 UNIX 系统调用 fork() 通过复制父进程来创建子进程。我的理解是,这之后几乎总是调用 exec() 来替换子进程的内存空间(包括文本段)。在 fork() 中复制父级的内存空间对我来说总是很浪费(尽管我意识到可以通过使内存段在写时复制从而只复制指针来最小化浪费)。无论如何,有谁知道为什么流程创建需要这种复制方法?
cjm*_*cjm 66
这是为了简化界面。替代fork和exec将类似于 Windows 的CreateProcess函数。请注意有多少参数CreateProcess,其中许多是具有更多参数的结构。这是因为一切你可能想控制对新工艺将被传递到CreateProcess。事实上,CreateProcess没有足够的参数,所以微软不得不添加CreateProcessAsUser和CreateProcessWithLogonW。
使用该fork/exec模型,您不需要所有这些参数。相反,过程的某些属性会在exec. 这允许您fork,然后换你想要的任何进程属性(使用相同的功能,你会正常使用),并随后 exec。在 Linux 中,fork没有参数,execve只有 3 个:要运行的程序,要给它的命令行,以及它的环境。(还有其他exec函数,但它们只是execveC 库提供的用于简化常见用例的包装器。)
如果要使用不同的当前目录启动进程: fork, chdir, exec.
如果要重定向 stdin/stdout: fork、关闭/打开文件、exec.
如果要切换用户:fork, setuid, exec.
所有这些都可以根据需要进行组合。如果有人想出了一种新的流程属性,您不必更改fork和exec。
正如 larsks 提到的,大多数现代 Unix 使用写时复制,因此fork不涉及大量开销。
除了 cjm 的回答之外,Single Unix Specification 还定义了一个名为vfork(). 该函数的工作方式与 fork 类似,只是如果 fork 进程除了尝试调用 exec 系列函数或调用_exit().
因此,定义行为的唯一用途几乎是:
pid_t ret = vfork();
if(ret == 0)
{
exec(...);
_exit(EXIT_FAILURE); //in case exec failed for any reason.
}
Run Code Online (Sandbox Code Playgroud)
那么有什么作用vfork呢?它是一种物美价廉的fork。在没有写时复制的实现中,生成的进程将与原始进程共享内存空间(因此出现未定义的行为)。在带有 copy-on-write 的实现中,vfork允许与 相同fork(),因为 copy-on-write 实现速度很快。
还有一个可选posix_spawn函数(和一个posix_spawnp函数)可以直接创建一个新进程。(也可以通过使用forkand的库调用来实现它们exec,并提供了一个示例实现。)