fork() 子進程和父進程

一、fork後的父子進程

由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的原因

至於那一個最先運行,可能與操作系統(調度算法)有關,而且這個問題在實際應用中並不重要,如果需要父子進程協同,可以通過原語的辦法解決。

  1. include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <stdlib.h>  
  4. #include <errno.h>  
  5.   
  6. int main(void)  
  7. {  
  8.         pid_t pid=fork();  
  9.         if(pid==0)  
  10.         {  
  11.                 int j ;  
  12.                 for(j=0;j<10;j++)  
  13.                 {  
  14.                         printf("child: %d\n",j);  
  15.                         sleep(1);  
  16.                 }  
  17.         }  
  18.         else if (pid>0)  
  19.         {  
  20.                 int i;  
  21.                 for(i=0;i<10;i++)  
  22.                 {  
  23.                         printf("parent: %d\n",i);  
  24.                         sleep(1);  
  25.                 }  
  26.         }  
  27.         else  
  28.         {  
  29.                 fprintf(stderr,"can't fork ,error %d\n",errno);  
  30.                 exit(1);  
  31.         }  
  32.         printf("This is the end !");  
  33. }  

二、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#

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章