在Unix/Linux中用fork函數建立一個新的進程。進程是由當前已有進程調用fork函數建立,分叉的進程叫子進程,建立者叫父進程。該函數的特色是調用一次,返回兩次,一次是在父進程,一次是在子進程。兩次返回的區別是子進程的返回值爲0,父進程的返回值是新子進程的ID。子進程與父進程繼續併發運行。若是父進程繼續建立更多的子進程,子進程之間是兄弟關係,一樣子進程也能夠建立本身的子進程,這樣能夠創建起定義關係的進程之間的一種層次關係。html
程序包含位於內存的多個組成部分,執行程序的過程將根據須要來訪問這些內容,包括文本段(text segment)、數據段(data segments)、棧(stack)和堆(heap)。文本段中存放CPU所執行的命令,數據段存放進程操做的全部數據變量,棧存放自動變量和函數數據,堆存放動態內存分配狀況數據。當進程被建立時,子進程收到父進程的數據副本,包括數據空間、堆、棧和進程描述符。linux
程序1:建立一個子進程,子進程對繼承的數據進行修改,而後分別輸出父子進程的信息。程序以下:面試
fork函數執行後程序結構圖以下:服務器
子進程與父進程並行執行,所以在父進程中sleep(10),讓子進程先執行,而後再執行父進程。併發
程序執行結果以下所示:函數
如何建立多個子進程呢?在開發併發服務器時,用到的進程池模型須要先建立指定書目的子進程。舉個例子,假如咱們如今須要建立2個子進程,很容易想到的是調用一個循環,執行fork函數2次便可。嘗試一下是否可行呢?代碼以下:測試
程序執行結果以下:spa
從結果來看,子進程的數目不是2而是3,這是爲何呢?先簡單的分析一下:從結果看出父進程ID爲10669,子進程的ID分別爲:10670、1067一、10672。3d
父子進程之間的關係以下:code
ID爲10670的子進程也調用fork函數,建立了一個進程。由於fork函數建立的進程是父進程的一份拷貝,保存了當前的數據空間、堆、棧及共享代碼區域。正確的方式應該是在子進程中跳出,中止繼續fork。改進的代碼以下:
程序執行結果以下:
從結果能夠看出這父進程(ID爲10789)建立了兩個子進程(ID分別爲:10790、10791)。
現有有這樣一個面試題,程序以下:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/types.h> 5 6 int main() 7 { 8 pid_t pid1; 9 pid_t pid2; 10 11 pid1 = fork(); 12 pid2 = fork(); 13 14 printf("pid1=%d,pid2=%d\n",pid1,pid2); 15 exit(0); 16 }
要求以下:
已知從這個程序執行到這個程序的全部進程結束這個時間段內,沒有其它新進程執行。
一、請說出執行這個程序後,將一共運行幾個進程。
二、若是其中一個進程的輸出結果是「pid1:1001, pid2:1002」,寫出其餘進程的輸出結果(不考慮進程執行順序)。
這個題目考查fork函數的理解。fork的做用是複製一個與當前進程同樣的進程。新進程的全部數據(變量、環境變量、程序計數器等)數值都和原進程一致,可是是一個全新的進程,並做爲原進程的子進程,父子進程並行的執行剩下的部分。
程序的執行過程以下:
(1)程序開始執行時候系統分配一個進程進行執行,稱該進程爲主進程P,進程ID題目未給,
(2)主進程執行到第一個fork函數的時候,建立一個新的子進程P1,有題目可知進程ID爲1001,fork函數有兩個返回值,返回pid=0表明子進程P1,pid1>0表明父進程P。
(3)如今有兩個進程P和P1,分別執行剩下部分,
(4)P進程(父進程,因此pid1=1001)調用fork建立子進程P2,返回兩個值中pid2=1002表示P2的進程ID返回給父進程P,pid2=0子進程P2自己,因此輸出pid1=1001, pid2=1002和pid1=1001,pid2=0。
(5)P1進程(子進程,因此pid1=0)調用fork建立子進程P3,進程ID類推爲1003,返回兩個值中pid2=1003表示P3的進程ID返回給父進程P1,pid2=0標識進程P3自己。因此輸出pid1=0,pid2=1003和pid1=0,pid2=0。
(6)執行整個結束。
根據以上分析可知答案:
一、一共執行了四個進程。(P0, P1, P2, P3)
二、另外幾個進程的輸出分別爲:
pid1:1001, pid2:0
pid1:0, pid2:1003
pid1:0, pid2:0
上機測試以下:
測試結果以下:
測試結果雖然不是1001,可是能夠看出理論分析過程是正確的。
題目來自:http://www.cnblogs.com/leoo2sk/archive/2009/12/11/talk-about-fork-in-linux.html