close

網路上找來的幾個資訊。

1.
call fork() 之後,就已經分出一個 child process 了, child 會從 return 的地方開始跑下去,parent 也是接著從同一個地方跑下去。兩者間唯一不同,就是fork() 的 return  value。

2.
要搞清楚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...

我想你比較困惑的就是,為什麼看上去程序中互斥的兩個分支都被執行了。在一個程序的一次執行中,這當然是不可能的;但是你看到的兩行輸出是來自兩個進程,這兩個進程來自同一個程序的兩次執行。

3.

http://www-h.eng.cam.ac.uk/help/tpl/unix/fork.html
http://nmc.nchu.edu.tw/linux/process.htm

參考以上兩個網站所得的暫時結論:
fork 所建的新子process會繼承其父process的許多變數(包括環境變數,檔案描述等),在fork呼叫後會有兩份(父,子)一樣的程式(orignial code)在執行。在父process中,進行fork呼叫後傳回的數值為其子process的process ID;而在新建立的子process中,fork的傳回值為0(因為兩個process使用同一份程式碼,故需以此來區分何者為父,何者為子)。
而exec則是一個程式去呼叫另一個程式,例如我們在linux的interperter環境(即所謂的"shell")下輸入"date",則接受到命令的shell會fork出一個子process(另一個shell),但這個shell的程式碼會被exec system call以"date"的程式碼來取代。
從這個地方看來,拿fork和exec來做比較好像有點不太對勁,如第二個網站所說的,fork-and-exec是UNIX中所有process運作的模式,要執行exec,一定是由一個被fork出來的子process來呼叫。兩者為先後關係。
真的要比,其差異應為:
fork:父process複製一個和自己一模一樣的子process,只有兩點不同:process ID和fork的傳回值。
exec:父process利用exec執行另一程式後,本身會被該程式完全取代。

//=====================================================================

因為是從google上查找到的,網頁已經不復以往,故未附上來源,如有著作權之問題請通知我,我會把此篇文章移掉。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Kurumi 的頭像
    Kurumi

    LiFeどうでしょう

    Kurumi 發表在 痞客邦 留言(0) 人氣()