Unix環境高階程式設計 七 fork函式總結

2021-09-07 16:58:48 字數 3599 閱讀 8544

在unix/linux中用fork函式建立乙個新的程序。程序是由當前已有程序呼叫fork函式建立,分叉的程序叫子程序,建立者叫父程序。該函式的特點是呼叫一次,返回兩次,一次是在父程序,一次是在子程序。兩次返回的區別是子程序的返回值為0,父程序的返回值是新子程序的id。子程序與父程序繼續併發執行。如果父程序繼續建立更多的子程序,子程序之間是兄弟關係,同樣子程序也可以建立自己的子程序,這樣可以建立起定義關係的程序之間的一種層次關係。

程式包含位於記憶體的多個組成部分,執行程式的過程將根據需要來訪問這些內容,包括文字段(text segment)、資料段(data segments)、棧(stack)和堆(heap)。文字段中存放cpu所執行的命令,資料段存放程序操作的所有資料變數,棧存放自動變數和函式資料,堆存放動態記憶體分配情況資料。當程序被建立時,子程序收到父程序的資料副本,包括資料空間、堆、棧和程序描述符。

程式1:建立乙個子程序,子程序對繼承的資料進行修改,然後分別輸出父子程序的資訊。程式如下:

1 #include 2 #include 3 #include 

4 #include 5 #include 6 #include 7 8 int add(int a,intb); 9 //全域性變數 10 int global = 99; 11 char buf = "input a string: "; 12 13 intmain() 14 26 if(pid == 0) //子程序 27 32 if(pid >0) //父程序 33 37 printf("pid=%d,ppid=%d,global=%d,val=%d\n",getpid(),getppid(),global,val); 38 write(stdout_fileno,buf,strlen(buf)); 39 read(stdin_fileno,str,100); 40 write(stdout_fileno,str,strlen(str)); 41 ret = add(global,val); 42 printf("global+val=%d\n",ret); 43 exit(0); 44 } 45 46 int add(int a,intb) 47

fork函式執行後程式結構圖如下:

子程序與父程序並行執行,因此在父程序中sleep(10),讓子程序先執行,然後再執行父程序。

程式執行結果如下所示:

如何建立多個子程序呢?在開發併發伺服器時,用到的程序池模型需要先建立指定書目的子程序。舉個例子,假如我們現在需要建立2個子程序,很容易想到的是呼叫乙個迴圈,執行fork函式2次即可。嘗試一下是否可行呢?**如下:

1 #include 2 #include 3 #include 

4 #include 5 #include 6 #include 7 8 intmain() 9 23 else if(pid== -1) 24 28 else 29 35 } 36 37 exit(0); 38 }

程式執行結果如下:

從結果來看,子程序的數目不是2而是3,這是為什麼呢?先簡單的分析一下:從結果看出父程序id為10669,子程序的id分別為:10670、10671、10672。

父子程序之間的關係如下:

id為10670的子程序也呼叫fork函式,建立了乙個程序。因為fork函式建立的程序是父程序的乙份拷貝,儲存了當前的資料空間、堆、棧及共享**區域。正確的方式應該是在子程序中跳出,停止繼續fork。改進的**如下:

1 #include 2 #include 3 #include 

4 #include 5 #include 6 #include 7 8 intmain() 9 24 else if(pid== -1) 25 29 else 30 38 } 39 40 exit(0); 41 }

程式執行結果如下:

從結果可以看出這父程序(id為10789)建立了兩個子程序(id分別為:10790、10791)。

現有有這樣乙個面試題,程式如下:

1 #include 2 #include 3 #include 4 #include 5 

6 intmain() 7

要求如下:

已知從這個程式執行到這個程式的所有程序結束這個時間段內,沒有其它新程序執行。

1、請說出執行這個程式後,將一共執行幾個程序。

2、如果其中乙個程序的輸出結果是「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)執行整個結束。

根據以上分析可知答案:

1、一共執行了四個程序。(p0, p1, p2, p3)

2、另外幾個程序的輸出分別為:

pid1:1001, pid2:0

pid1:0, pid2:1003

pid1:0, pid2:0

上機測試如下:

測試結果如下:

測試結果雖然不是1001,但是可以看出理論分析過程是正確的。

題目來自:

unix環境高階程式設計

unix 日曆時間 自1970 年1 月1 日00 00 00 以來的國際標準時間 utc 程序時間 cpu 時間 時鐘時間 程序執行時間的總量。使用者cpu 時間 執行使用者指令時間量。系統cpu 時間 執行核心所經歷時間。命令 time 第三章至第七章 原子操作 任何乙個要求多於1 個函式呼叫的...

unix環境高階程式設計

檔案描述符file descriptor通常是乙個小的非負整數,核心用以標識乙個特定程序正在訪問的檔案。當核心開啟乙個現有檔案或建立乙個新檔案時,它都返回乙個檔案描述符。在讀寫檔案時,可以私用這個檔案描述符。按管理,每當執行乙個新程式時,所有的shell都為其開啟了3個標準檔案描述符 標準輸入,標準...

UNIX環境高階程式設計

本書是被譽為unix程式設計 聖經 的advanced programming in the unix environment一書的更新版。在本書第1版出版後的十幾年中,unix行業已經有了巨大的變化,特別是影響unix程式設計介面的有關標準變化很大。本書在保持了前一版風格的基礎上,根據最新的標準對...