轉自Linux下fork()、vfork()、clone()和exec()的區別html
前三個和最後一個是兩個類型。前三個主要是Linux用來建立新的進程(線程)而設計的,exec()系列函數則是用來用指定的程序替換當前進程的全部內容。因此exec()系列函數常常在前三個函數使用以後調用,來建立一個全新的程序運行環境。Linux用init進程啓動其餘進程的過程通常都是這樣的。函數
下面說fork、vfork和clone三個函數。這三個函數分別調用了sys_fork、sys_vfork、sys_clone,最終都調用了do_fork函數,差異在於參數的傳遞和一些基本的準備工做不一樣。可見這三者最終達到的最本質的目的都是建立一個新的進程。在這裏須要明確一下,Linux內核中沒有獨立的「線程」結構,Linux的線程就是輕量級進程,換言之基本控制結構和Linux的進程是同樣的(都是經過struct task_struct管理)。 fork是最簡單的調用,不須要任何參數,僅僅是在建立一個子進程併爲其建立一個獨立於父進程的空間。fork使用COW(寫時拷貝)機制,而且COW了父進程的棧空間。 vfork是一個過期的應用,vfork也是建立一個子進程,可是子進程共享父進程的空間。在vfork建立子進程以後,父進程阻塞,直到子進程執行了exec()或者exit()。vfork最初是由於fork沒有實現COW機制,而不少狀況下fork以後會緊接着exec,而exec的執行至關於以前fork複製的空間所有變成了無用功,因此設計了vfork。而如今fork使用了COW機制,惟一的代價僅僅是複製父進程頁表的代價,因此vfork不該該出如今新的代碼之中。在Linux的manpage中隊vfork有這樣一段話:It is rather unfortunate that Linux revived this specter from the past. The BSD man page states: "This system call will be eliminated when proper system sharing mechanisms are implemented. Users should not depend on the memory sharing semantics of vfork() as it will, in that case, be made synonymous to fork(2)." clone是Linux爲建立線程設計的(雖然也能夠用clone建立進程)。因此能夠說clone是fork的升級版本,不只能夠建立進程或者線程,還能夠指定建立新的命名空間(namespace)、有選擇的繼承父進程的內存、甚至能夠將建立出來的進程變成父進程的兄弟進程等等。clone和fork的調用方式也很不相同,clone調用須要傳入一個函數,該函數在子進程中執行。此外,clone和fork最大不一樣在於clone再也不復制父進程的棧空間,而是本身建立一個新的。