2011-12-07 130 views
1

我看到这样的SIGCHLD处理器的一些例子:SIGCHLD处理程序重新安装

void child()                             
{                              
    wait(0);                           
    signal(SIGCHLD, child);  
} 
void server_main() 
{ 
    ... 
    signal(SIGCHLD, child); 
    ... 
    for(;;;) { 
     ... 
     switch(fork()) { 
     ... 
     } 
    } 

有两个部分在混淆我的处理程序: 1)。当孩子终止或停止时,SIGCHLD被捕获。那么为什么需要在处理程序中调用wait?信号已经到达。 2)。为什么需要重新安装SIGCHLD处理程序。信号调用是否会一劳永逸地安装处理程序?

谢谢!

回答

2
  1. 当子进程执行完毕 时,会触发SIGCHLD。但它仍然会在进程表中(作为所谓的僵尸进程的一个 ),以便让父级获取子级的退出 值。调用wait()将清除该子进程的进程表 。
  2. 如果您只创建n子进程,那么当所有子进程都死亡时,信号处理程序仍然没有到位。

我建议你看看sigaction来代替,因为signal的行为因Unix而异。

+0

谢谢,我看到了第一点。对于第二个,信号处理程序是为父权安装的?为什么当多个子进程死亡可能会导致信号处理程序不起作用? – Oxdeadbeef

+0

请看看sarnold的解释,他解释得相当不错。 – halfdan

1

是不是信号调用会一次性安装处理程序?

你不能依赖这种行为;也许信号处理程序将被清除,也许它会持续。这是历史信号处理问题的一部分。该signal(3)手册页对我的系统报告:

When a signal occurs, and func points to a function, it is 
    implementation-defined whether the equivalent of a: 


      signal(sig, SIG_DFL); 

    is executed or the implementation prevents some 
    implementation-defined set of signals (at least including 
    sig) from occurring until the current signal handling has 
    completed. 

不可靠的信号已经在SysVr4引入标准化,POSIX.1-2001 sigaction(2)基于信号被更换近:

struct sigaction { 
     void  (*sa_handler)(int); 
     void  (*sa_sigaction)(int, siginfo_t *, void *); 
     sigset_t sa_mask; 
     int  sa_flags; 
     void  (*sa_restorer)(void); 
    }; 

    int sigaction(int signum, const struct sigaction *act, 
       struct sigaction *oldact); 

这是可悲的是更复杂来编写代码,但是一旦编写完代码,您就不必担心是否需要重新安装处理程序 - 而且您不必担心信号在处理信号时第二次到达。

相关问题