2011-03-21 161 views
3

我正在写一个程序,它使用fork创建子进程并在完成时对它们进行计数。 我如何确定我不会失去信号? 当主程序仍然处理先前的信号时,如果小孩发送信号会发生什么?是信号“失落”?我怎样才能避免这种情况?如何确保在使用暂停()时不会丢失信号?

void my_prog() 
{ 
    for(i = 0; i<numberOfDirectChildrenGlobal; ++i) {  
     pid = fork(); 
     if(pid > 0)//parent 
      //do parent thing 
     else if(0 == pid) //child 
      //do child thing 
     else 
      //exit with error 
    } 

    while(numberOfDirectChildrenGlobal > 0) { 
     pause(); //waiting for signal as many times as number of direct children 
    } 

    kill(getppid(),SIGUSR1); 
    exit(0); 
} 

void sigUsrHandler(int signum) 
{ 
    //re-register to SIGUSR1 
    signal(SIGUSR1, sigUsrHandler); 
    //update number of children that finished 
    --numberOfDirectChildrenGlobal; 
} 

回答

5

建议使用sigaction而不是signal,但在这两种情况下,它都不会提供您所需要的。如果一个孩子在前一个信号仍在处理的过程中发送信号,它将成为一个未决信号,但是如果发送了更多的信号,它们将被丢弃(在没有阻塞传入信号的系统上,信号可以在重建处理程序并再次导致丢失信号)。没有解决方法。

通常会做的是假设某些信号丢失,并让处理程序照顾现有的孩子。

在你的情况,而不是从你的孩子发送信号,只是让孩子们终止。一旦它们终止,应该使用父母的SIGCHLD处理程序来获取它们。与WNOHANG选项一起使用waitpid可确保父母即使在同一时间终止所有孩子也会收到。

例如,计数退出儿童的数量SIGCHLD处理器可以是:

pid_t pid; 

while((pid = waitpid(-1, NULL, WNOHANG)) > 0) { 
     nrOfChildrenHandled++; 
} 
+0

谢谢你的回答。但这不完全是我想要的。我不想等到我们的孩子们都完成了。 – Noga 2011-03-23 05:43:42

+0

如果我用SA_NODEFER使用sigaction,它会安全吗?该文档说:SA_NODEFER不要阻止从它自己的信号处理程序接收信号。 – Noga 2011-03-23 05:45:53

+0

对该选项使用sigaction将调用处理程序,即使它正在处理另一个信号。但是,根据处理程序何时被调用,在处理程序执行期间,当几个信号同时发送时,可能会丢失信息。您可以使用ubiquite建议的实时信号,但是您可以执行的操作也受到限制。信号不是一个事件驱动的框架。基本上,你需要重新思考你在做什么,因为信号并不意味着被这样使用。 – Milan 2011-03-23 09:05:26

0

使用sigaction而不是信号来注册您的处理程序,并确保信号的传递。