2011-10-03 103 views
4

我很難理解fork()命令在不同場景下執行的操作。下面是我的書,一些示例代碼:與fork相混淆()

int main() { 
    int a = 12; 
    int b = 9; 
    int fid = fork(); 

    if (fid == 0) { 
     a++; 
    } 
    else { 
     wait(NULL); 
     b = b - 5; 
    } 

    printf("program exit. a = %d, b = %d\n", a, b); 
    return 0; 
} 

有人能走我通過什麼叉()命令在這種情況下,這樣做也許會給一些例子來澄清?

+0

請注意,處理'fork()'時沒有多線程(標記已移除)。您正在處理多個進程(多處理),而不是單個進程內的多個線程(多線程)。 –

+0

fork()也可以返回-1,也許你可以用switch(fid){...}來處理。 –

+0

@JonathanLeffler注意。謝謝! – raphnguyen

回答

12
    [main] 
       a = 12 
       b = 9 

       fork() 
        | 
        | 
    +--------------+--------------+ 
    |        | 
    |        | 
[parent]      [child] 

fid = 1234      fid = 0 
wait(NULL)      a++ 
    ...       printf("a = 13, b = 9"); 
    ...       return 0 
    ...       <exit> 
b = b - 5 
printf("a = 12, b = 4"); 
return 0 
<exit> 

fork()後,執行有計劃的兩個副本。每個進程都有自己的變量副本,所以現在有兩個a,兩個b等等。這兩個程序之間的唯一區別是從fork()返回的值:在子進程中fork()返回0;在父進程中,它返回子進程的PID。

子進程增量爲a,打印值爲ab,然後退出。

父進程首先等待子進程終止。只有在孩子完成後繼續,從b減去5,打印出ab,然後退出。

wait(NULL)確保子進程的打印輸出始終在父進程之前出現,因此您將始終以可靠的順序獲得相同的輸出。沒有它,你將無法依靠這兩個打印輸出的順序。它們將是相同的信息,只是以不可預測的順序。

+0

非常感謝!我想知道如何處理需要輸出的問題,這樣做很有意義,所以正確的輸出是'程序退出.a = 13,b = 9',然後是'程序退出。 a = 12,b = 4'? – raphnguyen

3

當您撥打fork()時,包括所有內存/變量等在內的整個過程都會被複制。

所以fork電話後,每個進程都有它的ab它開始分別129自己的副本。

進程0將增加它自己的副本a。過程1將減少(5)它自己的副本b

所以他們應該打印:

Process 0: a = 13, b = 9 
Process 1: a = 12, b = 4 
4
  1. a設置爲12,b設定爲9

  2. fork叫,我們現在有兩個過程。

  3. 父節點獲取子節點的PID,並轉到else子句。孩子得到0,並轉到if子句。

  4. 父母等待孩子完成。

  5. 孩子增加其副本a。所以a現在在孩子中是13歲,在父母中是12歲。

  6. 孩子出口,輸出139

  7. 父母從其b副本中減去5,所以b現在在父母中爲4。

  8. 父母退出,輸出124

注意,孩子和家長的執行fork後的確切順序是不能保證的,但因爲父等待孩子完成它做任何事情之前,它不會改變結果。

另外,請注意,讓這兩個進程正常退出是不好的做法。當一個進程正常退出時,它會運行清理處理程序,這可能會混淆其他進程,例如,通過更改共享文件描述中的文件位置,導致數據損壞。

+0

非常感謝您的一步一步。在這種情況下,在父進程完成wait()調用之後,你會說它會被阻塞,直到子進程結束(在子進程輸出'13'和'9'之後? – raphnguyen

+0

不客氣。是的, 「等待」電話的目的是阻止父母,直到孩子完成(或不可重新啓動的信號中斷呼叫) –

+0

晶晰的解釋,再次感謝!我希望我的書有更多的練習例子。 – raphnguyen

0

及其O/P是 父:: A = 12,B = 4 兒童::一個= 13,B = 9

既是過程同時執行,但兩者都具有局部變量的不同拷貝的,b so local var。受到一個進程的影響將不會被另一個進程看到,因爲兩個進程都在自己的副本上工作