2013-04-30 45 views
0

這是一個過去的紙質考試問題,我有麻煩解決。對於四標誌:請幫忙解釋這個C/linux代碼使用fork()

考慮,其採用在Unix系統中發現的叉()系統調用下面的C片段:一個圖(以樹的形式)

while (fork()==0) { 
    if (fork()==0) break; 
} 

畫出清楚地示出將通過執行此代碼生成的父子結構。在實踐中運行此代碼的最終效果是什麼?

我認爲它不斷創建子進程,但我無法在代碼的上下文中解釋它。這段時間是否每次都持續調用fork,還是每次都在if語句中調用?

謝謝!

+0

它被稱爲兩次。 – Shark 2013-04-30 12:35:12

+1

請參閱「叉炸彈」。 – paxdiablo 2013-04-30 12:36:22

+0

fork()在調用進程中返回子進程的PID,在子進程中返回0。所以它會繼續產生子進程,這會自己產生一個子進程。對? :) – Shark 2013-04-30 12:38:40

回答

7

甲執行while循環運行,直到在括號內的條件是假的。在這種情況下,這將是:直到fork()的返回值不等於0。

fork()的回報是:

成功時,子進程的PID在父返回,並且在孩子中返回0。失敗時,在父項中返回-1,不創建子進程,並且適當地設置errno。

所以一旦fork成功執行有2個進程(父和一個新的子進程)。其中一個將返回0(子進程),另一個(父進程)將返回一些其他值(子進程的PID)。

因此,這告訴你,代碼永遠運行,因爲每個子進程將繼續執行while()循環。

說你的父母是PID = 0 ,第一個孩子是PID = 1 等代碼的第一次運行會是這樣的:

while(fork()==0) // now there are two processes, the child which returns 0 and the 
{     // parent which returns 1 (the new child's pid) 

    if(fork() == 0) break; // this code is now only executed by the child (1) as the 
          // parent already left the while loop since it's return was 
          // not == 0 
          // once this code executes there are 2 processes running 
          // child(1) will return child(2)'s PID, child(2) will 
          // return 0 and will enter the if and break from the loop 
    // now here it's only the original child(1) running again 
} 

所以你最終了類似:

0 is the original parent, it makes a child and leaves 
1 is the original child, it creates a child(2) and then goes to the while loop again 
    where it generates 3 before leaving 
2 is the child of 1 where it leaves because of the break in the if 
3 now hits the if and generates 4 (which leaves because of the break) 
3 now goes back to while and generates 5 then leaves, 
etc 
etc 
       +--> 4 
       | 
       | (if) 
       | 
0 --> 1 -+--> 3 ---> 5 
     | 
     |(if) 
     | 
     +--> 2 

† - 這些都是不現實的PID,同時運行在任何現代的Linux發行版的用戶空間代碼來獲得,但他們更容易閱讀,然後真正的RANDO m字符串,所以我正在使用它們。

+0

更改「說你的父母是PID」到一個隨機pid,這似乎是正確的:) – Shark 2013-04-30 12:48:18

+0

優秀的解釋。謝謝你 – dahui 2013-04-30 12:49:01

+0

@Shark - 我爲你的關注增加了一個腳註,但我堅持使用較小的數字,因爲它們更易於理解和閱讀。 – Mike 2013-04-30 12:55:38

4
while (fork()==0) { 
    if (fork()==0) break; 
} 

第一行之前,說有一個id過程6282.

執行

while (fork()==0) 

現在後,有兩個進程,原來一個id爲6282,和一個新的用另一個ID 6283處理(說),現在第二個過程被認爲是原始過程的孩子。 現在只有id 6283的子進程進入循環,因爲在子上下文中fork()的返回值是零,而在父上下文中,返回值是創建的子進程的id。

第二條語句下面通過的處理中執行6283

if (fork()==0) break; 

現在的6283子進程將執行break語句,由於上面所說的原因,叉()的返回值是零子環境,因此子進程6283從循環中斷開。

現在while()循環的下一次迭代是通過僅由過程6283.

+0

謝謝隊友,我會upvote的答案,但我沒有足夠的代表:( – dahui 2013-04-30 12:52:41

+0

@ user2253489,沒問題,我只是希望你瞭解整個叉( )api,無論如何只要看看fork()的[man page](http://linux.die.net/man/2/fork)... – 2013-04-30 12:56:56