由fork創建的新進程被稱爲子進程(child process)。該函數被調用一次,但返回兩次。兩次返回的區別是子進程的返回值是0,而父進程的返回值則是新進程(子進程)的進程 id。將子進程id返回給父進程的理由是:因爲一個進程的子進程可以多於一個,沒有一個函數使一個進程可以獲得其所有子進程的進程id。對子進程來說,之所以fork返回0給它,是因爲它隨時可以調用getpid()來獲取自己的pid;也可以調用getppid()來獲取父進程的id。(進程id 0總是由交換進程使用,所以一個子進程的進程id不可能爲0 )。
fork之後,操作系統會複製一個與父進程完全相同的子進程,雖說是父子關係,但是在操作系統看來,他們更像兄弟關係,這2個進程共享代碼空間,但是數據空間是互相獨立的,子進程數據空間中的內容是父進程的完整拷貝,指令指針也完全相同,子進程擁有父進程當前運行到的位置(兩進程的程序計數器pc值相同,也就是說,子進程是從fork返回處開始執行的),但有一點不同,如果fork成功,子進程中fork的返回值是0,父進程中fork的返回值是子進程的進程號,如果fork不成功,父進程會返回錯誤。
可以這樣想象,2個進程一直同時運行,而且步調一致,在fork之後,他們分別作不同的工作,也就是分岔了。這也是fork爲什麼叫fork的原因
至於那一個最先運行,可能與操作系統(調度算法)有關,而且這個問題在實際應用中並不重要,如果需要父子進程協同,可以通過原語的辦法解決。
- include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- int main(void)
- {
- pid_t pid=fork();
- if(pid==0)
- {
- int j ;
- for(j=0;j<10;j++)
- {
- printf("child: %d\n",j);
- sleep(1);
- }
- }
- else if (pid>0)
- {
- int i;
- for(i=0;i<10;i++)
- {
- printf("parent: %d\n",i);
- sleep(1);
- }
- }
- else
- {
- fprintf(stderr,"can't fork ,error %d\n",errno);
- exit(1);
- }
- printf("This is the end !");
- }
二、fork出的子進程和父進程的繼承關係
fork出來的子進程,基本上除了進程號之外父進程的所有東西都有一份拷貝,基本就意味着不是全部,下面我們要說的是子進程從父進程那裏繼承了什麼東西,什麼東西沒有繼承。還有一點需要注意,子進程得到的只是父進程的拷貝,而不是父進程資源的本身。由子進程自父進程繼承到:
1.進程的資格(真實(real)/有效(effective)/已保存(saved)用戶號(UIDs)和組號(GIDs))
2.環境(environment)
3.堆棧
4.內存
5.打開文件的描述符(注意對應的文件的位置由父子進程共享,這會引起含糊情況)
6.執行時關閉(close-on-exec) 標誌 (譯者注:close-on-exec標誌可通過fnctl()對文件描述符設置,POSIX.1要求所有目錄流都必須在exec函數調用時關閉。更詳細說明,參見《UNIX環境高級編程》 W. R. Stevens, 1993, 尤晉元等譯(以下簡稱《高級編程》), 3.13節和8.9節)
7.信號(signal)控制設定
8.nice值 (譯者注:nice值由nice函數設定,該值表示進程的優先級,數值越小,優先級越高)
進程調度類別(scheduler class)(譯者注:進程調度類別指進程在系統中被調度時所屬的類別,不同類別有不同優先級,根據進程調度類別和nice值,進程調度程序可計算出每個進程的全局優先級(Global process prority),優先級高的進程優先執行)
8.進程組號
9.對話期ID(Session ID) (譯者注:譯文取自《高級編程》,指:進程所屬的對話期(session)ID, 一個對話期包括一個或多個進程組, 更詳細說明參見《高級編程》9.5節)
10.當前工作目錄
11.根目錄 (譯者注:根目錄不一定是“/”,它可由chroot函數改變)
12.文件方式創建屏蔽字(file mode creation mask (umask))(譯者注:譯文取自《高級編程》,指:創建新文件的缺省屏蔽字)
13.資源限制
14.控制終端
子進程所獨有:
進程號
1.不同的父進程號(譯者注:即子進程的父進程號與父進程的父進程號不同, 父進程號可由getppid函數得到)
2.自己的文件描述符和目錄流的拷貝(譯者注:目錄流由opendir函數創建,因其爲順序讀取,顧稱“目錄流”)
3.子進程不繼承父進程的進程,正文(text), 數據和其它鎖定內存(memory locks)(譯者注:鎖定內存指被鎖定的虛擬內存頁,鎖定後,4.不允許內核將其在必要時換出(page out),詳細說明參見《The GNU C Library Reference Manual》 2.2版, 1999, 3.4.2節)
5.在tms結構中的系統時間(譯者注:tms結構可由times函數獲得,它保存四個數據用於記錄進程使用中央處理器 (CPU:Central Processing Unit)的時間,包括:用戶時間,系統時間, 用戶各子進程合計時間,系統各子進程合計時間)
6.資源使用(resource utilizations)設定爲0
8.阻塞信號集初始化爲空集(譯者注:原文此處不明確,譯文根據fork函數手冊頁稍做修改)
9.不繼承由timer_create函數創建的計時器
10.不繼承異步輸入和輸出
原文地址:http://blog.csdn.net/koudaidai/article/details/8014782#