2013-07-17 33 views
0

這裏是我使用2個fork()系統調用一個接一個的代碼 - 它實際上是如何工作的?2個或更多分叉系統調用如何工作?

#include <unistd.h> 
#include <iostream.h> 
using namespace std; 

int main() 
{ 
    cout << "0. I am process " << getpid() << endl; 
    (void) fork(); 
    cout << "1. I am process " << getpid() << endl; 
    (void) fork(); 
    cout << "2. I am process " << getpid() << endl; 
} 

我得到的輸出:
0.我處理27701
1.我處理25915
1.我處理27701
2.我處理27781
2.我上午過程26170
2.我處理27701

這是我用過的3叉的系統調用下一個程序,我該如何得到這樣的輸出?如果我要手動解決這個代碼,那麼邏輯是什麼?

#include <unistd.h> 
#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "0. I am process " << getpid() << endl; 
    (void) fork(); 
    cout << "1. I am process " << getpid() << endl; 
    (void) fork(); 
    cout << "2. I am process " << getpid() << endl; 
    (void) fork(); 
    cout << "3. I am process " << getpid() << endl; 
} 

在這裏,我得到的輸出:
0.我處理27116
1.我處理26147
2.我處理27371
2.我處理26147
3我是處理24416
3.我處理27371
3.我處理27508
3.我處理26147
1.我處理27116
2.我處理21406
2.我處理27116
3.我處理27369
3.我處理21406
3.我處理26752
3.我處理27116

+0

這裏有很多關於'fork'如何在這種複雜情況下工作的問題。只畫一幅畫。 –

+0

我需要邏輯來繪製圖片!如果可能的話,請解釋第一個程序的邏輯,如果我理解了,那麼我會自己嘗試第二個程序。 –

+0

你的第一個程序應該輸出4個標記爲'2'的行,有4個不同的PID。 25915的輸出發生了什麼? –

回答

1

你的程序完全錯誤。您應該千萬不要忽視fork的結果。

閱讀Advanced Linux programming書和fork(2)手冊頁(仔細閱讀該頁面幾次)。

典型代碼應該是:

pid_t pid1 = fork(); 
    if (pid1<0) { perror("fork1 failed"); exit(EXIT_FAILURE); } 
    else if (pid1 == 0) { 
    // you are in the child process 
    } 
    else // pid1>0 
    { // you are in the parent process 
    } 

並且同樣爲pid_t pid2=fork();,然後pid_t pid3=fork();等.... 所以每次調用fork應該處理3箱子fork結果的(即失敗<0,子進程==0,父進程>0

在原則上,你有3個即27點的可能性。但是,您可以儘早處理故障案例,即可保留2個即8個。可能性

請不要忘記處理fork的故障。您可能會降低您的流程限制(使用setrlimit(2)使用RLIMIT_NPROC或等效ulimit bash內建)來緩解fork失敗的測試。

+0

我把這個測試代碼用來理解fork()在一個接一個地使用時是如何工作的,在下一次我使用一個真正的程序時,我會記住你的修正。謝謝。 –

0

只需繪製一棵樹,其中每個根節點都是一個fork調用,葉節點是它後面的代碼。


在第一個程序中,你的子程序「父...」是父程序,在fork調用之後,該行之後的整個程序執行兩次。因此兩個「1 ...」輸出行。

現在還有另一個分叉調用。這次有3個進程正在運行(1.您調用的原始父代,2.它產生的孩子3.孩子本身產生另一個孫子。)
因此,3「2 ...」輸出行。

5

fork()每次打電話時都是一樣的。一個新進程被創建爲當前進程的精確副本,並且兩者都繼續執行,就像它們都只是從fork()函數調用返回一樣,只是返回值不同。在你的情況下,你扔掉了返回值,所以它們只是相同的過程。

讓我們爲您的第一個示例繪製圖片。從我只是做了一個run(因爲你把你的問題的輸出未完成)輸出樣本:

0. I am process 25597 
1. I am process 25597 
2. I am process 25597 
1. I am process 25598 
2. I am process 25599 
2. I am process 25598 
2. I am process 25600 

你開始用PID 25597.一個過程它打印0行,然後叉。這產生兩個過程:

  25597   # prints "0" 
      /\ 
      /\ 
     / \ 
     25597 25598  # both print "1" 

到目前爲止好。現在這兩個這些新進程再次調用fork()。完整的樹最終看起來像這樣:

    25597 
        /\ 
       /\ 
       / \ 
       / \ 
       /  \ 
      25597  25598  # both print "1" 
       /\   /\ 
      /\  /\ 
      / \ / \ 
     25597 25599 25598 25600 # all four print "2" 

的25599的實際位置和25600不能從輸出猜到了,遺憾的是 - 他們可以反過來了。

對於你的3- fork()的例子,你只需要做同樣的事情,但它會在圖中有另一個層次 - 最後會有8個進程打印「3」線。

+0

謝謝!你讓解釋變得如此簡單我一直在互聯網上游蕩只是爲了找到一個簡單的解釋! –

0

當調用fork()時,會創建並運行子進程。所以,你所得到的子進程執行一次下面的語句:

cout << "1. I am process " << getpid() << endl; 

此外,當另一個叉被調用時,會創建另一個子進程運行於未來「的cout」語句。但是,父進程也運行。這發生在第三個fork()上。

所有這些都發生在第一個fork()的子進程中。在此之後,第一個分支的父進程也運行以顯示您的輸出。