fork是最難理解的概念之一:它執行一次卻返回兩個值。
首先我們來看下fork函式的原型:
#include
#include
pid_t fork(void);
返回值:
負數:如果出錯,則fork()返回-1,此時沒有建立新的程序。最初的程序仍然執行。
零:在子程序中,fork()返回0
正數:在負程序中,fork()返回正的子程序的pid
其次我們來看下如何利用fork建立子程序。
建立子程序的樣板**如下所示:
pid_t child;
if((child = fork())<0)
/*錯誤處理*/
else if(child == 0)
/*這是新程序*/
else
/*這是最初的父程序*/
fock函式呼叫一次卻返回兩次;向父程序返回子程序的id,向子程序中返回0,
這是因為父程序可能存在很多過子程序,所以必須通過這個返回的子程序id來跟蹤子程序,
而子程序只有乙個父程序,他的id可以通過getppid取得。
fork的精闢剖析
程式如下:
#include ;
#include ;
main ()
pid_t pid;
pid=fork();
if (pid < 0) printf("error in fork!");
else if (pid == 0)
printf("i am the child process, my process id is %dn",getpid());
else
printf("i am the parent process, my process id is %dn",getpid());
} 結果是
[root@localhost c]# ./a.out
i am the child process, my process id is 4286
i am the parent process, my process id is 4285
要搞清楚fork的執行過程,就必須先講清楚作業系統中的「程序(process)」概念。乙個程序,主要包含三個元素:
o. 乙個可以執行的程式;
o. 和該程序相關聯的全部資料(包括變數,記憶體空間,緩衝區等等);
o. 程式的執行上下文(execution context)。
不妨簡單理解為,乙個程序表示的,就是乙個可執行程式的一次執行過程中的乙個狀態。作業系統對程序的管理,典型的情況,是通過程序表完成的。程序表中的每 乙個表項,記錄的是當前作業系統中乙個程序的情況。對於單 cpu的情況而言,每一特定時刻只有乙個程序占用 cpu,但是系統中可能同時存在多個活動的(等待執行或繼續執行的)程序。乙個稱為「程式計數器(program counter, pc)」的暫存器,指出當前占用 cpu的程序要執行的下一條指令的位置。當分給某個程序的 cpu時間已經用完,作業系統將該程序相關的暫存器的值,儲存到該程序在程序表中對應的表項裡面;把將要接替這個程序占用 cpu的那個程序的上下文,從程序表中讀出,並更新相應的暫存器(這個過程稱為「上下文交換(process context switch)」,實際的上下文交換需要涉及到更多的資料,那和fork無關,不再多說,主要要記住程式暫存器 pc指出程式當前已經執行到**,是程序上下文的重要內容,換出 cpu的程序要儲存這個暫存器的值,換入cpu的程序,也要根據程序表中儲存的本程序執行上下文資訊,更新這個暫存器)。
好了,有這些概念打底,可以說fork了。當你的程式執行到下面的語句:
pid=fork();
作業系統建立乙個新的程序(子程序),並且在程序表中相應為它建立乙個新的表項。新程序和原有程序的可執行程式是同乙個程式;上下文和資料,絕大部分就是原程序(父程序)的拷貝,但它們是兩個相互獨立的程序!此時程式暫存器pc,在父、子程序的上下文中都聲稱,這個程序目前執行到fork呼叫即將返回(此時子程序不占有cpu,子程序的pc不是真正儲存在暫存器中,而是作為程序上下文儲存在程序表中的對應表項內)。問題是怎麼返回,在父子程序中就分道揚鑣。
父程序繼續執行,作業系統對fork的實現,使這個呼叫在父程序中返回剛剛建立的子程序的pid(乙個正整數),所以下面的if語句中pid<0, pid==0的兩個分支都不會執行。所以輸出i am the parent process...
子程序在之後的某個時候得到排程,它的上下文被換入,佔據 cpu,作業系統對fork的實現,使得子程序中fork呼叫返回0。所以在這個程序(注意這不是父程序了哦,雖然是同乙個程式,但是這是同乙個程式的另外一次執行,在作業系統中這次執行是由另外乙個程序表示的,從執行的角度說和父程序相互獨立)中pid=0。這個程序繼續執行的過程中,if語句中 pid<0不滿足,但是pid= =0是true。所以輸出i am the child process...
為什麼看上去程式中互斥的兩個分支都被執行了?在乙個程式的一次執行中,這當然是不可能的;但是你看到的兩行輸出是來自兩個程序,這兩個程序來自同乙個程式的兩次執行。
fork之後,作業系統會複製乙個與父程序完全相同的子程序,雖說是父子關係,但是在作業系統看來,他們更像兄弟關係,這2個程序共享**空間,但是資料空間是互相獨立的,子程序資料空間中的內容是父程序的完整拷貝,指令指標也完全相同,但只有一點不同,如果fork成功,子程序中fork的返回值是0, 父程序中fork的返回值是子程序的程序號,如果fork不成功,父程序會返回錯誤。
可以這樣想象,2個程序一直同時執行,而且步調一致,在fork之後,他們分別作不同的工作,也就是分岔了。這也是fork為什麼叫fork的原因。
在程式段裡用了fork()之後程式出了分岔,派生出了兩個程序。具體哪個先執行就看該系統的排程演算法了。
如果需要父子程序協同,可以通過原語的辦法解決。
二: 程序的建立:
建立乙個程序的系統呼叫很簡單.我們只要呼叫fork函式就可以了.
#include
pid_t fork();
當乙個程序呼叫了fork以後,系統會建立乙個子程序.這個子程序和父程序不同的地方只有他的程序id和父程序id,其他的都是一樣.就象父程序轉殖 (clone)自己一樣.當然建立兩個一模一樣的程序是沒有意義的.為了區分父程序和子程序,我們必須跟蹤fork的返回值. 當fork掉用失敗的時候(記憶體不足或者是使用者的最大程序數已到)fork返回-1,否則fork的返回值有重要的作用.對於父程序fork返回子程序的 id,而對於fork子程序返回0.我們就是根據這個返回值來區分父子程序的. 父程序為什麼要建立子程序呢?前面我們已經說過了linux是乙個多使用者作業系統,在同一時間會有許多的使用者在爭奪系統的資源.有時程序為了早一點完成任 務就建立子程序來爭奪資源. 一旦子程序被建立,父子程序一起從fork處繼續執行,相互競爭系統的資源.有時候我們希望子程序繼續執行,而父程序阻塞,直到子程序完成任務.這個時候我們可以呼叫wait或者waitpid系統呼叫.
總結一下有三:
1,派生子程序的程序,即父程序,其pid不變;
2,對子程序來說,fork返回給它0,但它的pid絕對不會是0;之所以fork返回0給它,是因為它隨時可以呼叫getpid()來獲取自己的pid;
3,fork之後父子程序除非採用了同步手段,否則不能確定誰先執行,也不能確定誰先結束。認為子程序結束後父程序才從fork返回的,這是不對的,fork不是這樣的,vfork才這樣。
函式返回值的問題
執行結果 1 您輸入的是23456 2 function text val 3 您輸入的是中國北京 text 23456 var s text window.alert s s 中國北京 function text val var s text 23456 window.alert s functi...
C C 函式返回值問題
函式返回值問題 在c c 中 內建型別 char short int long float double 結構體型別 聯合體型別union 列舉型別enum 函式返回值分為三種情況 1.函式返回值小於等於4位元組時,返回值由eax暫存器帶回。2.函式返回值大於4位元組小於等於時,返回值是由eax和e...
fread fwrite函式返回值問題
函式原型 include size t fread void ptr,size t size,size t nmemb,file stream size t fwrite const void ptr,size t size,size t nmemb,file stream nmemb是需要讀取的資...