【发布时间】:2011-06-18 21:08:28
【问题描述】:
我希望在 Google 上找到这四个之间的区别,并且我预计会有大量关于这方面的信息,但是这四个调用之间确实没有任何可靠的比较。
我开始尝试编译一种基本的概览,看看这些系统调用之间的差异,这就是我得到的。所有这些信息是否正确/我是否遗漏了任何重要的信息?
Fork:fork 调用基本上复制了当前进程,几乎在所有方面都相同(并非所有内容都被复制,例如,某些实现中的资源限制,但想法是创建尽可能接近的副本可能)。
新进程(子进程)获得不同的进程 ID(PID),并以旧进程(父进程)的 PID 作为其父进程 PID(PPID)。因为这两个进程现在运行的代码完全相同,所以它们可以通过 fork 的返回码来判断哪个是哪个——子进程得到 0,父进程得到子进程的 PID。这就是全部,当然,假设 fork 调用有效 - 如果没有,则不会创建子节点并且父节点会收到错误代码。
Vfork : vfork 和 fork 的基本区别在于,当使用 vfork() 创建新进程时,父进程会暂时挂起,子进程可能会借用父进程的地址空间。这种奇怪的情况一直持续到子进程退出,或者调用 execve(),此时父进程
进程继续。
这意味着 vfork() 的子进程必须小心避免意外修改父进程的变量。特别是子进程不能从包含vfork()调用的函数返回,也不能调用exit()(如果需要退出,应该使用_exit();其实对子进程也是如此一个普通的 fork())。
Exec : exec 调用是一种基本上用新程序替换整个当前进程的方法。它将程序加载到当前进程空间并从入口点运行它。 exec() 用函数指向的可执行文件替换当前进程。除非出现 exec() 错误,否则控制永远不会返回到原始程序。
Clone :克隆,作为fork,创建一个新进程。与 fork 不同,这些调用允许子进程与调用进程共享其部分执行上下文,例如内存空间、文件描述符表和信号处理程序表。
当使用clone创建子进程时,它会执行函数应用程序fn(arg)。 (这与 fork 不同,后者从原始 fork 调用开始在子进程中继续执行。) fn 参数是一个指向函数的指针,该函数由子进程在其执行开始时调用。 arg 参数被传递给 fn 函数。
当 fn(arg) 函数应用程序返回时,子进程终止。 fn 返回的整数是子进程的退出代码。子进程也可以通过调用 exit(2) 或在收到致命信号后显式终止。
信息获取形式:
- Differences between fork and exec
- http://www.allinterview.com/showanswers/59616.html
- http://www.unixguide.net/unix/programming/1.1.2.shtml
- http://linux.about.com/library/cmd/blcmdl2_clone.htm
感谢您抽出宝贵时间阅读本文! :)
【问题讨论】:
-
为什么vfork不能调用exit()?还是不回来? exit() 不只使用_exit() 吗?我也在努力理解:)
-
@Gnuey:因为它可能(如果它的实现方式不同于
fork(),它在 Linux 中,可能是所有 BSD 中)借用其父级的地址空间。它所做的任何事情,除了调用execve()或_exit()之外,都有很大的可能会弄乱父母。特别是,exit()调用atexit()处理程序和其他“终结器”,例如:它刷新 stdio 流。从vfork()孩子返回可能(与以前相同的警告)会弄乱父母的堆栈。 -
我想知道父进程的线程会发生什么;它们都是克隆的还是只有调用
fork系统调用的线程? -
@LazerSharks vfork 产生一个类似线程的进程,其中内存在没有写时复制保护的情况下共享,因此执行堆栈操作可能会破坏父进程。
标签: linux process fork exec clone