詳解linux中fork、vfork、clone函數(shù)的區(qū)別
在linux系統(tǒng)中,fork(),vfork()和clone函數(shù)都可以創(chuàng)建一個(gè)進(jìn)程,但是它們的區(qū)別是什么呢???本文就這三者做一個(gè)較深入的分析?。?!
1.fork()
fork()函數(shù)的作用是創(chuàng)建一個(gè)新進(jìn)程,由fork創(chuàng)建的進(jìn)程稱為子進(jìn)程,fork函數(shù)調(diào)用一次返回兩次,子進(jìn)程返回值為0,父進(jìn)程返回子進(jìn)程的進(jìn)程ID。我們知道,一個(gè)進(jìn)程的地
址空間主要由代碼段,數(shù)據(jù)段,堆和棧構(gòu)成,那么p2就要復(fù)制相關(guān)的段到物理內(nèi)存。原始的unix系統(tǒng)的實(shí)現(xiàn)的是一種傻
瓜式的進(jìn)程創(chuàng)建,這些復(fù)制包括:
(1) 為子進(jìn)程的頁表分配頁面,確定頁表的位置;
(2)為子進(jìn)程的頁分配頁面,確定子進(jìn)程頁面的位置;
(3)初始化子進(jìn)程的頁表;
(4)把父進(jìn)程的頁復(fù)制到子進(jìn)程對應(yīng)的頁中
從圖中我們可以看出除了正文段外,子進(jìn)程的所有其它段都分配了物理空間,并將父進(jìn)程的相關(guān)內(nèi)容拷貝過來。父進(jìn)程的task_struct結(jié)構(gòu)中的打開文件描述符,進(jìn)程組ID,
回話ID都進(jìn)行復(fù)制。
下面通過簡單的代碼檢測一下fork()函數(shù):
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys types.h=""> #include <pthread.h> #include #include <iostream> using namespace std; int main() { int num = 1; int child; if(!(child =fork())) { cout<<&num<<endl; address:="" alt="\" child="vfork()))" class="brush:java;" else="" father="" img="" include="" int="" is:="" namespace="" num="1;" num:="" pid="" pre="" son="" src="/uploadfile/Collfiles/20170421/201704210949041534.jpg" sys="" types.h="" using=""><p>測試結(jié)果:</p><p><img alt="\" src="/uploadfile/Collfiles/20170421/201704210949041535.jpg" style="width: 630px; height: 201.393px;"></p><p>從測試結(jié)果中我們可以看到,在子進(jìn)程修改了num變量的值后,父進(jìn)程的num的值也發(fā)生改變,說明對于子進(jìn)程和父進(jìn)程來說,它們操作的是同一個(gè)地方的num值,下面就是vfork的示意圖:</p><p><img alt="\" src="/uploadfile/Collfiles/20170421/201704210949041536.jpg" style="width: 508px; height: 375px;"></p><p>可以看出子進(jìn)程直接共享了父進(jìn)程的虛擬進(jìn)程空間。</p><p>3.clone()</p><p> clone()函數(shù)是linux系統(tǒng)中,用來創(chuàng)建輕量級進(jìn)程。</p><p>函數(shù)原形:</p><pre class="brush:java;">int clone(int (*fn)(void *), void *child_stack, int flags, void *arg); 下面是flags可以取的值 標(biāo)志 含義 CLONE_PARENT 創(chuàng)建的子進(jìn)程的父進(jìn)程是調(diào)用者的父進(jìn)程,新進(jìn)程與創(chuàng)建它的進(jìn)程成了“兄弟”而不是“父子” CLONE_FS 子進(jìn)程與父進(jìn)程共享相同的文件系統(tǒng),包括root、當(dāng)前目錄、umask CLONE_FILES 子進(jìn)程與父進(jìn)程共享相同的文件描述符(file descriptor)表 CLONE_NEWNS 在新的namespace啟動(dòng)子進(jìn)程,namespace描述了進(jìn)程的文件hierarchy CLONE_SIGHAND 子進(jìn)程與父進(jìn)程共享相同的信號處理(signal handler)表 CLONE_PTRACE 若父進(jìn)程被trace,子進(jìn)程也被trace CLONE_VFORK 父進(jìn)程被掛起,直至子進(jìn)程釋放虛擬內(nèi)存資源 CLONE_VM 子進(jìn)程與父進(jìn)程運(yùn)行于相同的內(nèi)存空間 CLONE_PID 子進(jìn)程在創(chuàng)建時(shí)PID與父進(jìn)程一致 CLONE_THREAD Linux 2.4中增加以支持POSIX線程標(biāo)準(zhǔn),子進(jìn)程與父進(jìn)程共享相同的線程群 下面的例子是創(chuàng)建一個(gè)線程(子進(jìn)程共享了父進(jìn)程虛存空間,沒有自己獨(dú)立的虛存空間不能稱其為進(jìn)程)。父進(jìn)程被掛起當(dāng)子線程釋放虛 存資源后再繼續(xù)執(zhí)行。</pre> 測試代碼1: <pre class="brush:java;">#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys types.h=""> #include <pthread.h> #include #include <iostream> using namespace std; #define FIBER_STACK 8192 int a; void * stack; int func(void *){ cout<<&a<<endl; a="" char="" creating="" int="" is="" is:="" my="" pid="" pre="" son="" stack="" the="" this="" void=""> 結(jié)果:<p><img alt="\" src="/uploadfile/Collfiles/20170421/201704210949041537.png" style="width: 630px; height: 201.393px;"></p><p>測試代碼2(做如下修改):</p><pre class="brush:java;">clone(func, (char *)stack + FIBER_STACK,CLONE_VFORK, 0);</pre> 結(jié)果: <p><img alt="\" src="http://chabaoo.cn/uploadfile/Collfiles/20170421/201704210949041538.png" style="display: block; width: 630px; height: 201.393px;"></p> <p>很明顯,在測試2中將CLONE_VM刪掉之后,子進(jìn)程和父進(jìn)程就不會(huì)公用頁表,子進(jìn)程創(chuàng)建新的頁表。從某種意義上來說,clone其實(shí)是fork和vfrok的更高層次版本,,它們的關(guān)</p> <p>系如下(《深入理解linux內(nèi)核》中描述):</p> <p> <strong>傳統(tǒng)的fork()系統(tǒng)調(diào)用在Linux中是用clone()實(shí)現(xiàn)的,其中clone()的flags參數(shù)指定為sigchld信號以及所有清0的clone標(biāo)志,而它的child_stack參數(shù)是父進(jìn)程當(dāng)前的堆棧</strong></p> <p><strong>指針,因此,父進(jìn)程和子進(jìn)程暫時(shí)共享一個(gè)用戶態(tài)堆棧。而vfork函數(shù)系統(tǒng)調(diào)用也是用clone實(shí)現(xiàn)的,其中clone()的參數(shù)flags指定為sigchld和CLONE_VFORK和CLONE_VM標(biāo)</strong></p> <p><strong>志,clone()的參數(shù)child_stack等于父進(jìn)程當(dāng)前的棧指針?。?!</strong></p> 。只是有一點(diǎn)不明白,把int a和void * stack挪到main函數(shù)里面之后,就會(huì)出現(xiàn)編譯錯(cuò)誤,顯示未定義a和stack,這點(diǎn)有些不懂,望高人指點(diǎn)!?。?! </endl;></iostream></assert.h></pthread.h></sys></unistd.h></stdlib.h></stdio.h></pre> </endl;></iostream></assert.h></pthread.h></sys></unistd.h></stdlib.h></stdio.h>
以上所述是小編給大家介紹的linux中fork、vfork、clone函數(shù)的區(qū)別,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Linux新技術(shù)對象存儲(chǔ)文件系統(tǒng)
Linux新技術(shù)對象存儲(chǔ)文件系統(tǒng)...2006-10-10Linux內(nèi)核模塊和驅(qū)動(dòng)的編寫
Linux內(nèi)核模塊和驅(qū)動(dòng)的編寫...2006-10-10