我看到一些SIGCHLD处理程序的例子,如:
void child()
{
wait(0);
signal(SIGCHLD, child);
}
void server_main()
{
...
signal(SIGCHLD, child);
...
for(;;;) {
...
switch(fork()) {
...
}
}
处理程序中有两个部分让我感到困惑:1). SIGCHLD在子进程终止或停止时被捕获。那么为什么需要在处理程序中调用wait呢?信号已经到了。2).为什么需要重新安装SIGCHLD处理器。是不是信号调用将一劳永逸地安装处理程序?
谢谢!
- SIGCHLD将在子进程完成时触发执行。然而,它仍将在进程表中(作为所谓的僵尸进程),以便让父进程取回退出孩子的价值。调用
wait()
将清除进程表 - 如果你只创建
n
子进程,那么当所有n
子进程死亡时,信号处理程序仍然存在是没有理由的。
我建议你看看sigaction
,因为signal
的行为在不同的unix中是不同的。
是不是信号调用将一劳永逸地安装处理器?
你不能依赖这个行为;也许信号处理程序将被清除,也许它将持续存在。这是历史信号处理问题的一部分。我的系统上的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中引入的基于sigaction(2)
的信号所取代,并在POSIX.1-2001中标准化:
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);
令人遗憾的是,这些代码编写起来更复杂,但是一旦您编写了代码,您就不必担心是否需要重新安装处理程序——并且您不必担心在处理信号时信号会第二次到达。