我在谷歌上查找了这四个系统调用的区别,本以为会有很多相关信息,但实际上并没有一个可靠的比较结果。
于是我试图编写一个基本的、快速了解这些系统调用之间差异的内容,以下是我整理的结果。其中是否有错误或遗漏了重要信息?
Fork
:fork 调用可以创建与当前进程几乎完全相同的另一个进程(并不是所有信息都被复制,例如在某些实现中的资源限制),新进程(子进程)会拥有独立的进程ID (PID),而其父进程的PID则成为它的父进程PID(PPID)。由于两个进程现在运行着完全相同的代码,因此它们可以通过 fork 的返回值来区分彼此——子进程得到 0,父进程得到子进程的 PID。当然,这基于 fork 调用有效——如果不是,则不会创建子进程,父进程会收到一个错误码。
Vfork
:使用 vfork()
创建新进程时,父进程暂时挂起,子进程可能借用父进程的地址空间。除非子进程退出或调用execve()
,否则这种奇怪的状态将继续存在,此时父进程会继续运行。
这意味着 vfork()
的子进程必须小心地避免意外修改父进程的变量。特别是,子进程不能从包含vfork()
调用的函数返回,也不能调用 exit()
(如果需要退出,则应使用_exit()
;实际上,这对于普通的fork()
的子进程也是正确的)。
Exec
: exec 调用可以将整个当前进程替换为一个新程序,它将程序加载到当前进程空间并从入口点运行。 exec()
将当前进程替换为函数指向的可执行文件。除非发生 exec()
错误,否则控制不会返回到原始程序。
Clone
:与 fork()
不同,clone()
允许子进程与调用进程共享其执行上下文的某些部分,例如内存空间、文件描述符表和信号处理程序表。
clone()
创建子进程时,它执行函数应用程序fn(arg)(这与fork()
不同,在fork()
调用点之后,子进程会继续执行)。 fn参数是指向在子进程开始执行时由子进程调用的函数的指针。 arg参数传递给fn函数。当fn(arg)函数应用程序返回时,子进程终止。由fn返回的整数是子进程的退出代码。 子进程也可以通过调用exit(2)
或在接收到致命信号后终止。
信息来自:
- fork和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
感谢您抽出时间阅读! :)
fork()
不同,Linux和大多数BSD都是这样)借用其父进程的地址空间。除了调用execve()
或_exit()
之外,它所做的任何事情都有很大的潜力会破坏父进程。特别是,exit()
调用atexit()
处理程序和其他“终结器”,例如:它刷新stdio流。从vfork()
子进程返回可能(与前面相同的警告)会破坏父进程的堆栈。 - ninjaljfork
系统调用的线程被克隆? - Mohammad Jafar Mashhadi