2011-12-05 97 views
2

你怎麼能等到所有的孩子和大孩子都退出了,沒有在信號處理程序中阻塞?這是我迄今的嘗試。等待孩子和孫子們

#include <signal.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 

int run = 1; 

void handler(int sig, siginfo_t *info, void *uap) 
{ 
    int exit_code; 

    printf("sigchld pid %d\n", info->si_pid); 
    pid_t pid = waitpid(-1, &exit_code, 0); 
    if (pid == -1) { 
     perror("waitpid()\n"); 
    } else { 
     printf("waitpid returned %d\n", pid); 
    } 
    // set run = 0 when all children exit 

    printf("end of sigchild handler\n"); 
} 

void main() { 

    struct sigaction chld; 
    chld.sa_sigaction = handler; 
    chld.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; 
    sigaction(SIGCHLD, &chld, NULL); 

    //procmask sigchld? 
    if (!fork()) { 
     if (!fork()) { 
      sleep(2); 
      printf ("grand-son exit: %d\n", getpid()); 
      exit (0); 
     } 
     sleep(1); 
     printf ("son exit: %d\n", getpid()); 
     exit (0); 
    } 

    while(run) 
     sleep(1); 

    printf("ciao\n"); 
} 
+3

你不能等待孫子;如果孩子沒有等待自己的孩子而離開,那麼這些孩子通常會被重新分配到「根」或「初始」過程。 (見http://en.wikipedia.org/wiki/Orphan_process。) – ruakh

+1

1)main returns int。 2)不要在信號處理程序中使用printf()。 3)分叉兩次是孫子從祖父進程中分離的一種方式(但是可能需要一些額外的系統調用來從終端(組)中分離) – wildplasser

回答

0

雖然這是事實,SIGCHLD和waitpid等,只有立即兒童工作,在UNIX系統上你經常可以「欺騙」從父母傳給孩子孫子繼承的資源一點點,並在進程終止時關閉。

例如,原來的進程可能會打開一個pipe,也許設置讀它close-on-exec,讓孩子和孫子繼承寫入結束。當原始進程準備好等待所有後代終止時,它會關閉其管道的寫入端,並且爲了其他描述符的可讀性而阻塞地執行read s或select s。當最後一個後代終止時,管道的讀端將傳遞一個EOF。

這種策略並不能保證 - 孩子或孫子可能謹慎地關閉繼承的文件描述符 - 但它通常工作得很好。

0

你需要的是等待功能: 等待,waitpid函數 - 等待一個子進程停止或終止。 編輯:都能跟得上:)

+0

我使用waitpid,你有沒有試過我的例子? – elmarco