linux - fork()、vfork()、exec()和clone()的区别

标签 linux process fork exec clone

我希望在 Google 上找到这四个之间的区别,我预计会有大量关于这方面的信息,但是这四个调用之间确实没有任何可靠的比较。

我开始尝试编译一种基本的概览,看看这些系统调用之间的差异,这就是我得到的。所有这些信息是否正确/我是否遗漏了任何重要的信息?

Fork :fork 调用基本上复制了当前进程,几乎在所有方面都相同(并非所有内容都被复制,例如,某些实现中的资源限制,但想法是创建尽可能接近副本)。

新进程(子进程)获得不同的进程 ID(PID),并以旧进程(父进程)的 PI​​D 作为其父进程 PID(PPID)。因为这两个进程现在运行的代码完全相同,所以它们可以通过 fork 的返回码来判断哪个是哪个 - 子进程得到 0,父进程得到子进程的 PID。这就是全部,当然,假设 fork 调用有效 - 如果没有,则不会创建子节点并且父节点会收到错误代码。

Vfork:vfork()fork()的基本区别在于当使用vfork创建新进程时(),父进程暂时挂起,子进程可能会借用父进程的地址空间。这种奇怪的情况一直持续到子进程退出,或者调用 execve(),此时父进程 进程继续。

这意味着 vfork() 的子进程必须小心避免意外修改父进程的变量。特别是,子进程不能从包含vfork()调用的函数返回,也不能调用exit()(如果需要退出,应该使用 _exit();实际上,对于普通 fork()) 的子节点也是如此。

Exec:exec调用是一种基本上用新程序替换整个当前进程的方法。它将程序加载到当前进程空间并从入口点运行它。 exec() 用函数指向的可执行文件替换当前进程。除非出现 exec() 错误,否则控制永远不会返回到原始程序。

Clone:clone(),作为fork(),创建一个新进程。与 fork() 不同,这些调用允许子进程与调用进程共享其部分执行上下文,例如内存空间、文件描述符表和信号处理程序表。

当使用clone()创建子进程时,它会执行函数应用fn(arg)(这与fork()不同>,其中从原始 fork() 调用的点开始在子进程中继续执行。) fn 参数是指向子进程调用的函数的指针在其执行之初。 arg 参数被传递给 fn 函数。

fn(arg)函数应用返回时,子进程终止。 fn 返回的整数是子进程的退出代码。子进程也可以通过调用 exit(2) 或在收到致命信号后显式终止。

信息来自:

感谢您抽出宝贵时间阅读本文! :)

最佳答案

  • vfork()是一个过时的优化。在良好的内存管理之前,fork()制作了 parent 内存的完整副本,因此非常昂贵。因为在许多情况下 fork()紧随其后的是 exec() ,它会丢弃当前的内存映射并创建一个新的映射,这是不必要的开销。如今,fork()不复制内存;它只是设置为“写时复制”,所以fork() + exec()vfork() 一样有效+ exec() .

  • clone()fork() 使用的系统调用.使用一些参数,它创建一个新进程,使用其他参数,它创建一个线程。它们之间的区别只是哪些数据结构(内存空间、处理器状态、堆栈、PID、打开的文件等)是共享的。

关于linux - fork()、vfork()、exec()和clone()的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4856255/

相关文章:

linux - 在下标中使用 exec 重定向标准输出

linux - 从入口点动态选择在主机上运行 Docker 的用户 GUI 和 UID

linux - 当大型父进程的子分支关闭时,如何防止 Perl 消耗大量内存?

c - 如何在 gdb 中的 fork() 之后调试子进程?

linux - Perl:如何在 linux 中为 .pl 文件设置 perl 版本

linux - Linux Ubuntu 14.04下安装Scratch 2

c - 当一个线程在 C 中阻塞时,为什么整个进程不会阻塞

c - 这段关于使用 fork() 在 C 中创建进程的代码会发生什么

c - 打印当前进程的打开文件

c - 运行 fork 并打印 hello