2012-02-13 86 views
5

enter image description here我不明白這個叉圖()

我們如何能得到這個過程與這種情況??過程的模式?

int main (int argc, char **argv) { 
    int i; 
    int pid; 
     for (i= 0; i < 3; i++) { 
      pid = fork(); 

      if (pid < 0) break;// with this condition i dont understand?? 

     } 
      while (wait(NULL) != -1); 
+3

如果這是#homework,請將其標記爲 – 2012-02-13 23:33:55

+0

該功能被稱爲「fork」,而不是「Fork」;我糾正了標題。 – 2012-02-14 00:05:49

回答

8

fork()將進程拆分爲兩部分,並返回0(如果此進程是子進程)或子進程的PID(如果此進程是父進程),否則返回-1。所以,這行:

if (pid < 0) break; 

說:「如果我們未能創建子進程退出循環」。

由於過程(圓圈)對應於循環中的fork()調用的方式,該圖有點令人困惑。主流程的三個子流程分別在i分別爲0,1和2時創建(請參閱本文底部的圖)。

由於循環繼續在雙方家長和從點叉子進程被稱爲,這是叉是如何發生的:

  • i == 0:叉稱爲原父。現在有兩個過程(頂部和左側)。
  • i == 1:fork在兩個現有進程中調用。新的孩子是從底部開始的第二層的最左邊的孩子,以及從底部開始的第三層的中間的孩子。現在有四個進程
  • i == 2:在所有現有進程中調用fork。新的兒童是所有剩餘的節點(底部節點,在從borrom第二層中的最右邊的兩個節點,並從底部的第三層中的最右邊的節點)
  • i == 3:所有8個處理退出循環

這裏再次與表示什麼i值是在循環過程中創建時數:

    -1 <--- this is the parent that starts the loop 
      / | \ 
      0 1 2 
     /\ | 
      1 2 2 
      | 
      2 
2

如果fork調用失敗,fork返回-1。它返回父親中的pid和孩子中的0。你所看到的情況對代碼的功能無關緊要;它只是說如果fork出現錯誤,然後退出循環。如果在fork調用中沒有錯誤,那麼將會構建圖中的進程樹。

原因是相同的循環將繼續在子進程中運行。因此,在分岔被叫時,孩子們也將繼續根據i的價值進行分岔。

3

要了解你必須依靠fork行爲的圖:它拆分過程在二,創建另一個相同的過程到第一個(PID除外)在一個新的內存位置。

如果你在一個循環,這就是發生叫它:

i=0第一進程也將被拆分,創建另一個進程將開始正是這點上運行(這樣會跳過第一個循環)。專注於第一個過程,它將繼續循環,在i=1時生成另一個過程。因此,第二個過程將從i=1開始,因此將跳過前兩個循環。第一個過程將在上次拆分爲i=2。但是,最後創建的副本將從i=2開始運行,因此它將退出循環並不會生成任何內容。

創建的第一個副本將從i=1開始循環,生成兩個進程,而第二個副本將從i=2開始,只生成一個副本。

你可以繼續這個推理,並理解其餘的圖。

正如其他人指出的,if (pid < 0)只是一個檢查,看看是否有錯誤,不會修改代碼的邏輯。

2

fork錯誤返回-1,其他值爲0或正數,所以行if (pid < 0) break;表示「如果出現錯誤,退出循環」。

假設沒有錯誤,它是這樣的:

在開始的時候,i=0,和你有一個過程。我們稱之爲p0

在行fork();,p0創建另一個進程。我們稱之爲p1

在他們的每個人中,我們有i++(所以現在i是1),我們再次迭代循環。

p0p1分別具有fork();命令,因此每個人都創建另一個進程。我們稱之爲新工藝p2p3

現在,在每個過程中,我們有i++,即將i設置爲2,然後我們再次運行循環。

我們擁有的4個流程中的每一個都運行fork();這一行,並創建一個新流程。所以現在我們也有p4,p5,p6,p7

每個進程都將其i增加爲3,然後,由於循環條件現在爲false,循環最終結束。

現在,8過程到達(分開)到下一行。

(事實上,每次迭代兩倍的進程數,因此,如果你改變了3到,例如,15,你將有2^15處理在最後。)