2016-08-02 29 views
3

讓我們假定存在具有PID = 1一個過程,它運行以下代碼:故障理解fork()的輸出

int a = fork(); 
int b = fork(); 
printf(「a: %d, b: %d\n」, a, b); 

讓我們進一步假設新PID旨意給出一個接一個,從而第二給定PID2,然後3

一種可能的輸出:

a:2, b:3 
a:2, b:0 
a:0, b:4 
a:0, b:0 

我有一些麻煩試圖瞭解上述代碼的輸出,尤其是爲什麼a:0, b:4a:2, b:3

回答

12

你知道

返回值是在孩子和家長在孩子的進程ID號的零,或-1時的錯誤。

所以,讓我們一步一步看看這裏發生了什麼。

fork()被調用,它會創建ID n一個新的子,然後在孩子0和父n返回。

因此,讓我們假設我們的過程爲pid 1,當調用第一個fork()時,它會創建一個pid爲2的進程,然後返回一個值。 a在過程2(孩子)中將具有值0,並且在過程1(父母)中將具有值2

然後每個進程將調用fork()並在父進程中將返回值分配給b。在孩子中,b將具有值0

無論如何,我認爲這個模式將簡化理解:

主要開始:

| 
| 
int a = fork(); // It creates a new process, and the old one continues going 
| 
|-------------------------| 
a = 2; /* Parent */  a = 0; // Child 
|       | 
|       | 
int b = fork();   int b = fork(); // Each one create a new process 
|       | 
|       |-----------------------------| 
|       /* Child -> Parent */   // Child -> Child 
|       a = 0; b = 4;     a = 0; b = 0 
| 
| 
| 
| 
|-----------------------------| 
/* Parent -> Parent */  // Parent -> Child 
a = 2; b = 3;     a = 2, b = 0; 
1

一個fork後,你可以是在父親(fork返回子的PID),或在子(fork返回0)。

第一次打電話給fork後,您將有2個過程:父親(您的示例中爲a = 2)和子女(a = 0)。

兩個都會分叉,父親(a = 2)會給一個孩子(b = 0)和一個新父親(b = 3)。孩子(a = 0)會給一個新的孩子(b = 0),其中的孩子將是父親(b = 4)。

你可能輸出是:

a:2, b:3 -> father and father 
a:2, b:0 -> father and child 
a:0, b:4 -> child and father 
a:0, b:0 -> child and child 
4

之前第一叉:

PID 1 (father) 
a = (not in scope yet) 
b = (not in scope yet) 

第一叉後:

PID 1 (father) 
a = 2 
b = (not in scope yet) 

PID 2 (child of 1) 
a = 0 
b = (not in scope yet) 

第二叉後:

PID 1 (father) 
a = 2 
b = 3 

PID 2 (child of 1) 
a = 0 
b = 4 

PID 3 (child of 1) 
a = 2 
b = 0 

PID 4 (child of 2) 
a = 0 
b = 0 
+0

謝謝。這可能是一個簡單的問題,但爲什麼在'PID 3'中,'a = 2'?怎樣才能讓'再見'2'? –

+1

由於3是1的孩子,因此直到第二次調用'fork'時才完整克隆1,包括'a'的值。 –

4

我還沒有想回答你的問題。它更多的是展示常用的模式。如果評論中只有正確的代碼格式,它可能是一個評論。

的基本結構與fork()是:

if (int PID = fork() == 0) { 
    //it's a child process 
} else { 
    //it's a parent process 
} 

使用簡單的

int PID1 = fork(); 
int PID2 = fork(); 

是非常危險的,你將幾乎肯定獲得Race condition

0
Original process: 
forks child A, and child B 
prints `a:2, b:3` 

    child A process: 
    forks child BB 
    prints `a:0, b:4` 

     child BB proess: 
     forks nothing 
     prints `a:0, b:0` 

    child B process: 
    forks nothing 
    prints `a:2, b:0` 

而且因爲你還沒有使用任何waitwaitpid這些可以以任意順序出現。