2012-01-04 110 views
2
#include <stdio.h> 
    #include <unistd.h> 
    int main() 
    { 
     fork(); 
     fork() && fork() || fork(); 
     fork(); 

    printf("forked\n"); 
    return 0; 
    } 

它會導致難以理解如何計算執行程序後產生的進程數? 幫我看看。fork()系統調用c

平臺--UBUNTU 10.04

+5

爲什麼不從編譯和運行開始,看看有多少「分叉」消息? – 2012-01-04 12:37:06

+4

是功課嗎?沒有理智的人會寫'fork()&& fork()||叉()'。你可以拆分這一行,並添加更多的調試輸出。 – ThiefMaster 2012-01-04 12:39:05

+1

我已經編譯了很多次,每次都得到不同的答案...看到這裏http://ideone.com/CXlkR – 2012-01-04 12:50:54

回答

8

讓我們跟隨叉樹,假設沒有叉的失敗

fork();

現在我們有兩個過程,到目前爲止,不管是誰的孩子,誰的父母,給他們打電話p1和p2

fork()的

這兩項工藝菌種另一個孩子,所以我們有4個過程,其中兩個(P3,P4),結果是零,另外兩個(P1和P2)是非零

&& fork() 

p1和p2再次分叉,給出p5和p6,總共有6個過程。在p1和p2中,&&的計算結果爲true,因此它們不會在此行再次分叉。爲P3,P4,P5,P6,所述&&評估爲假,所以他們叉

   || fork(); 

這裏,產卵四個新的工藝,給出總共6 + 4 = 10。

fork();

每一次的10個進程叉

,使得20

2

你不應該使用這樣的fork()。決不。而且,儘管如此,在現實生活中你不需要這樣做。 如何使用它:

int main() { 
    /* code */ 
    pid_t pid = fork(); 
    if (pid < 0) { 
     /* error, no child process spawned */ 
    } 
    if (pid > 0) { 
     /* we are the parent process, pid is the process ID of the ONE child process spawned */ 
    } 
    /* else, we are the child process, running exactly one command later the fork() was called in the parent. */ 
    /* some more code */ 
    return 0; 
} 
+0

你可能是對的,但這並不能真正回答這個問題。 – 2012-01-04 12:44:37

+0

嘿,慢下來!你顯然沒有閱讀我的答案。在評論中,有執行或未執行的子進程的數量。我想回答他的問題。 – 2012-01-04 12:48:56

1

保存文件,說的那樣fork-count.c。然後用gcc fork-count.c -o fork-count進行編譯。然後你可以運行它並用./fork-count | wc -l來統計輸出的行數。

+0

我已經編譯了很多次,但它給出了不同的結果。 – 2012-01-04 12:54:41

+0

你是說你可以連續多次運行該程序並獲得不同的結果? – 2012-01-04 12:58:21

+0

閱讀以上評論plz。 – 2012-01-04 13:00:57

3
fork(); 

fork系統調用返回一個整數:在子進程父進程和0的過程中的PID。如果發生錯誤,則不會創建進程並返回-1。

||&&是邏輯運算符。

如果操作的結果是左手操作數的評價後知道,他們需要短路(即不計算右邊操作數):

  • ||操作其右操作數是沒有評估,如果它的左操作!= 0
  • &&操作其右操作數是不是如果leftt操作評估是== 0
0

我發現這個問題on Geeks for Geeks的正確解釋:

叉()系統調用創建子進程的不斷增長的二叉樹的葉子。如果我們調用fork()兩次,它會產生22 = 4個進程。所有這4個過程都構成了二叉樹的葉子。一般來說,如果我們是level 1,並且fork()無條件地調用,我們將在level(l + 1)處有2l個進程。它相當於級別爲(l + 1)的二叉樹中最大子節點的數量。

作爲另一個例子,假設我們無條件地調用了3次fork()調用。我們可以使用具有3個級別的完整二叉樹來表示產生的進程。在級別3,我們將有23 = 8個子節點,這對應於正在運行的進程的數量。

對C/C++的邏輯運算符的說明:

邏輯算& &具有比||更優先級,並且已經從左到右關聯性。執行左操作數後,最終結果將被估計,右操作數的執行取決於左操作數的結果以及操作類型。

在AND的情況下(& &),在評估左操作數之後,只有在左操作數評估爲非零時才評估右操作數。在OR(||)的情況下,在評估左操作數之後,僅當左操作數評估爲零時才評估右操作數。

叉的返回值():

叉的手冊頁()引用的返回值以下摘錄,

「如果成功,子進程的PID在父返回,並且在孩子中返回0。失敗時,-1返回父進程,沒有創建子進程,並且適當地設置了errno。「

PID就像進程句柄一樣,表示爲unsigned int。我們可以得出結論,fork()將在父對象中返回一個非零值,並在子對象中返回零。讓我們分析一下這個程序。爲了便於符號,標記每個叉(),如下所示,

 #include <stdio.h> 
    int main() 
     { 
     fork(); /* A */ 
     (  fork() /* B */ && 
     fork() /* C */) || /* B and C are grouped according to precedence */ 
     fork(); /* D */ 
     fork(); /* E */ 

     printf("forked\n"); 
     return 0; 
    } 

enter image description here 前兩個叉()調用被稱爲無條件。

在0級,我們只有主進程。主(圖中的m)將創建子C1,兩者都將繼續執行。孩子們的創作順序越來越高。

在1級,我們有m和C1運行,並準備執行fork() - B.(注意B,C和D命名爲& &和||運算符的操作數)。初始表達式B將在每個在此級別運行的子進程和父進程中執行。

在等級2,由於fork() - B由m和C1執行,所以我們有m和C1作爲父母,C2和C3作爲孩子。

fork() - B的返回值在父項中非零,在子項中爲零。由於第一個運算符是& &,由於返回值爲零,子項C2和C3將不會執行下一個表達式(fork()-C)。父母進程m和C1將繼續使用fork()-C。子進程C2和C3將直接執行fork() - D,以評估邏輯OR運算的值。

在3級,我們有m,C1,C2,C3作爲跑步過程,C4,C5作爲孩子。該表達式現在被簡化爲((B & & C)|| D),並且此時(C)的值是顯而易見的。在父母中,它是非零的,在兒童中是零。因此,父母知道總體結果B & & C || D,將跳過執行fork() - D。因爲在子節點(B & & C)評估爲0時,它們將執行fork()-D。我們應該注意到,在第2級創建的子節點C2和C3將如上所述也運行fork() - D。

在級別4,我們將m,C1,C2,C3,C4,C5作爲運行進程,將C6,C7,C8和C9作爲子進程。所有這些進程無條件地執行fork() - E,併產生一個孩子。

在5級,我們將有20個進程在運行。該程序(在Ubuntu Maverick上,GCC 4.4.5)打印了「叉」20次。一旦由根父(主)和由兒童休息。總體來說,將會產生19個進程。