2010-03-08 107 views
1

有什麼辦法來區分程序中由不同的fork()函數創建的子進程。fork()內fork()

global variable i; 

SIGCHLD handler function() 
{ 
    i--; 
} 

handle() 
{ 
    fork() --> FORK2 
} 

main() 
{ 
    while(1) 
    { 
    if(i<5) 
    { 
     i++; 
     if((fpid=fork())==0) --> FORK1 
      handle() 
     else (fpid>0) 
      ..... 
    } 
    } 
} 

有什麼辦法,我可以通過與fork1和FORK2創建子進程區分?因爲我試圖在SIGCHLD處理程序函數中減小全局變量'i'的值,並且它應該僅針對由FORK1創建的進程遞減..

我嘗試使用數組並保存子進程ID由FORK1創建的進程由父進程完成。我會遞減的「我」只值,如果死去的孩子的進程ID是在陣列內...

但我面臨的一個問題,下面的場景

child1,parent1,child1打死的child2的child2殺死,parent2

child1的櫃面,因爲它是parent1陣列正確更新後死亡。

但是,在它的pid值被數組中的parent2更新之前,child2會被殺死的情況是什麼?由於child2 PID值不在數組中,所以'SIG'信號處理函數內部的'i'值不會相應地減少。

+0

可能的重複:http://stackoverflow.com/questions/340283/avoiding-a-fork-sigchld-race-condition – jschmier 2010-03-16 22:44:41

+0

嗯......實際上我還沒有找到它.. – codingfreak 2010-03-25 06:34:45

+0

你是如何設置信號處理程序?用'signal','bsd_signal'或者'sigaction'? – Random832 2015-02-09 18:54:31

回答

2

既然你已經儲蓄要遞減在SIGCHLD處理器的i值PID列表,可以觸發您正在接受額外SIGCHLD在更新列表中的一部分。

在使用sigprocmask()執行信號處理程序期間,您可以屏蔽/阻止其他SIGCHLD信號。這應該爲您提供足夠的時間來更新您的進程ID數組/列表,而不用擔心接收另一個SIGCHLD。當信號處理程序完成時,屏蔽掩碼必須返回到其原始值。

嘗試添加類似於以下到您SIGCHLD處理的東西:

sigset_t mask; 
sigset_t orig_mask; 

sigemptyset (&mask); 
sigaddset (&mask, SIGCHLD); 

/* temporarily mask/block SIGCHLD signals and save original mask */ 
if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) { 
    perror ("sigprocmask - %s", strerror(errno)); 
} 

/* process SIGCHLD via waitpid() and update PID list as necessary */ 
... 

/* restore original mask */ 
if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) { 
    perror ("sigprocmask - %s", strerror(errno)); 
} 

更新

重新審視你的問題後,我看到你有一個種族conditon其中一個子進程在父進程可以將其PID添加到列表之前終止。

一個可能的解決方案仍然是使用sigprocmask()來阻止關鍵部分期間的SIGCHLD信號。在這種情況下,在您呼叫fork()之前,您需要先阻止SIGCHLD信號,並在PID已添加到列表中後,在父代碼中解除阻塞。如果孩子死亡,信號處理程序將在您解鎖信號後被調用,並且這應該保證PID在列表中。

+0

其實我沒有面臨任何問題處理SIGCHLD信號處理程序函數中的數組List ...最初使用子進程的進程ID更新數組由父進程完成。因此,在執行順序的情況下,就像.... child1,parent1,child2,child3,parent2,parent3 ...一樣。如果child2在執行parent2代碼之前被殺死,那麼ARRAY不會因child2 PID而更新SIGCHLD信號處理程序不會減少i值,因爲數組中沒有pid – codingfreak 2010-03-09 02:57:13

+0

現在,我對問題有了更好的理解,因此我已經更新了相應的答案。 – jschmier 2010-03-09 05:48:53

+0

你的意思是我應該阻止fork()之前的SIGCHLD信號並在父進程中解除阻塞。 – codingfreak 2010-03-09 06:53:31

0

使用:

getppid() function . 
+0

你的意思是我應該在SIGCHILD信號處理函數中使用getppid()...?在這種情況下,它沒有多大用處......? – codingfreak 2010-03-09 02:50:02

0

如果我沒有理解好了,你可能會感興趣的waitpid()系統調用。 它允許你等待一個特定的孩子(給定一個PID)。因此,如果您跟蹤由fork1和fork2創建的pid,則只有在fork1中的孩子死亡時,才能減少您的i變量。

+0

爲了維護由fork1創建的所有子進程的列表我正在使用父進程中的數組來更新具有子進程ID和SIGCHLD處理程序函數的數組我試圖減少我的值,只有當它的PID是在陣列中.. 但是有一個問題..如果子進程死得如此之快,即使在父進程中的代碼不執行,那麼陣列沒有得到適當的值更新.. – codingfreak 2010-03-09 02:46:53