2010-05-21 49 views
2

我們在C中編寫一個像shell一樣的bash,但是後臺進程有問題。 事情是,當沒有&時,父親等待子進程,我們爲SIGCHLD做了一個signal_handler,它裏面有一個等待。如何在後臺執行後避免殭屍進程

我們想要避免的主要問題是:signal_handler總是執行(有背景和前臺進程),所以如果signal_handler在父進程之前捕獲到SIGCHLD,那麼父親的等待沒有孩子可以等待,所以它返回一個錯誤。

我們取決於他們之前執行過誰,我們希望如果沒有&,那麼signal_handler等待在父親執行之前不會收集子女。

任何幫助都是非常重要的。提前致謝。

+0

正在做作業嗎? – fortran 2010-05-21 10:22:27

+0

設置「父親」進程除了檢查已終止的孩子之外什麼也不做。從而減少了一個crach的可能性。你應該在cild過程中做所有的工作。 – eaanon01 2010-05-21 10:23:26

回答

1

你的問題對我來說有點不清楚,但我會提及一些我曾考慮過爲類似情況做過的事情。

當您創建一個進程時,您可以暫時阻止SIGCHLD並將子進程(以及如何處理它)的記錄放入表中。

child_table_node_t * node = malloc(sizeof(child_table_node_t)); 
// err check that 
child_table_node_init(node, type_of_child_stuff); 

sigset_t old, set; 

sigemptyset(&set); 
sigaddset(&set, SIGCHLD); 
sigprocmask(SIG_BLOCK, &set, &old); 
pid_t pid = fork(); 
if (pid > 0) { 
    node->pid = pid; 
    add_to_table(alive_children, node); 
    sigprocmask(SIG_SETMASK, &old, NULL); 
    // other stuff 
} else { 
    sigprocmask(SIG_SETMASK, &old, NULL); 
    if (!pid) { 
     // do child stuff 
    } else { 
     // do parent with no child stuff 
    } 
} 

handle_sigchild那麼可以看一下兒誰在表芯(或停止或其他),併爲他們做點什麼。我建議將它們從alive_children表中刪除,並在信號處理程序中將它們放入dead_children表中,以便應用程序可以更輕鬆地處理它們並釋放其內存。如果你想跟上被停止和死亡的孩子,那麼會有一點複雜的B/C,你不會希望從活着的表中刪除它們。在非信號代碼中遍歷表可能更容易找到更改的節點。如果是這種情況,您可以在不添加或刪除節點的情況下阻止信號。

然後,您的應用程序可以根據該過程的表節點中存儲的數據執行特定於該子節點的操作。如果孩子在前臺,那麼它的死亡(或停止動作)就是將退出代碼存儲到退出代碼變量中,並開始再次從終端或腳本獲取命令。如果新去世的孩子是後臺進程,那麼您只需記錄其退出代碼並在下次打印命令提示符(如果處於交互模式)之前將其報告給終端。

+1

您的建議非常有用。我們最終創建了一個數組來存儲後臺進程的PID,以便只等待signal_handler中的這些PID。 我們真的很感謝你的回答;)。 – PID 2010-05-22 10:50:38

+0

我很高興這很有幫助。祝你的項目好運:-) – nategoose 2010-05-23 19:37:46