2011-02-02 111 views
2

我有一個這樣的代碼...殭屍處理和叉

c = fork(); 
if(c==0) { 
    close(fd[READ]); 

    if (dup2(fd[WRITE],STDOUT_FILENO) != -1) 
     execlp("ssh", "ssh", host, "ls" , NULL); 
    _exit(1); 

} 
close(fd[WRITE]); 

FD [READ]和FD [WRITE]是管文件描述符。

當我連續運行它時,當我使用ps ax時有很多殭屍進程。如何糾正這一點?這是因爲我沒有使用父級來等待子進程的退出狀態...

回答

7

如果您無意爲您的子進程使用wait,請將SIGCHLD處理程序設置爲SIG_IGN以使內核自動獲取您的子項,例如。

signal(SIGCHLD, SIG_IGN); 
2

是的,父級必須等待子級返回狀態。您可以通過在父進程中捕獲SIGCHILD,然後在捕獲方法中調用waitpid來異步執行此操作。

0

是的,應該從父級調用waitpid()。 waitpid()將清理當前處於終止狀態的父進程的任何子進程。

您可以在下面的代碼添加到您的程序:

if(c>0) 
{ 
while(1){ 
ret = waitpid(-1,&status,0); 

if(ret>0){ 
if(WIFEXITED(status)){ 
    if(WEXITSTATUS(status) == 0){ 
     printf("child process terminated normally and successfully\n"); 
    } 
    else{ 

     printf("child process terminated normally and unsuccessfully\n"); 
    } 
} 
else{ 

     printf("child process terminated abnormally and unsuccessfully\n"); 
    } 
} 
if(ret<0) { 
    break; 
    } 
    } 
} 

供參考:更多waitpid函數。

第一個參數設置爲-1,使得waitpid()將清理此父進程的任何子進程,該子進程當前處於終止狀態。第一個參數也可以是+ ve - 在本例中,waitpid )只會清除特定的子進程。最常見的用法是將第一個參數設置爲-1,同時參考waitpid()的手冊頁。 第二個參數用於提取子進程的終止/退出狀態代碼 - 當系統調用API被調用時,waitpid()系統調用API填充狀態字段。 最後一個字段是flags字段 - 當前未使用 - 在大多數情況下,flags字段將設置爲0 - 意味着系統調用API的默認行爲!如果您確實需要使用標誌,請參閱waitpid()的手冊頁。

注意: 在您提交的代碼中,如果execlp()失敗,將調用_exit(1)。所以你可以把execlp()失敗的條件和條件_exit()可以被調用。原因是,execlp()函數僅在發生錯誤時纔會返回。

修改後的代碼可以是象下面這樣:

c = fork(); 
if(c==0) { 
close(fd[READ]); 

if (dup2(fd[WRITE],STDOUT_FILENO) != -1) 
    ret_execlp = execlp("ssh", "ssh", host, "ls" , NULL); 
if(ret_execlp == -1) { 
     printf("execlp is failed"); 
     _exit(1); 
    } 
} 
close(fd[WRITE]); 

我明白上述2個答案。希望這個答案可以給予更多的清晰。謝謝。