【发布时间】:2020-08-02 02:58:30
【问题描述】:
在我的程序中,我正在监听传入的 SIGCHLD 信号以避免僵尸。
代码:
void myhandler(int signo)
{
printf("test");
int status;
pid_t pid;
while((pid = waitpid(-1, &status, WNOHANG)) > 0)
++count;
}
int main(int argc, char const *argv[])
{
struct sigaction sigchld_action;
memset(&sigchld_action,0,sizeof(sigchld_action));
sigchld_action.sa_handler = &myhandler;
sigaction(SIGCHLD,&sigchld_action,NULL);
if(fork() == 0){
exit(0);
}
if(fork()==0){
exit(0);
}
if(fork()==0){
exit(0);
}
while(wait(NULL) > 0)
++count;
return 0;
}
问题是,分叉子的数量和 printf("test") 的输出数量有时不匹配。分叉子的数量大于数量 printf("test")。
这段代码是否保证不会有僵尸?如果是,它是如何做到这一点的?它没有打印正确数量的“测试”。 waitpid() 是否在 while 内多次清除死去的孩子?
当这个信号处理程序被调用时会发生什么,同时另一个孩子可能会死掉。默认情况下,信号将被阻止。(当处理程序运行时,另一个孩子可能会死亡)。 waitpid 是否清除信号处理程序运行时发送的信号的进程?
另外,计数器不相等。 (static volatile int) 或者我尝试了原子整数。
【问题讨论】:
-
您不能在信号处理程序中安全地使用像
printf()这样的 stdio 函数,顺便说一句。 -
@Shawn 是的我知道,但是如果使用原子计数器,结果是一样的。
-
他简单的意思是相同类型的未决信号没有排队,它们被丢弃。此外,信号处理程序在处理程序期间屏蔽信号(除非您明确阻止它这样做)。所以他们到了,但没有及时得到处理。你不会以这种方式收获所有的孩子——僵尸会出现。
-
其实我最后的说法是错误的,可能所有的孩子还在while循环中被收割。即使处理程序只被调用一次。检查调用了多少次处理程序在这里不是一个有效的指标。毕竟,您的代码以这种方式是安全的,对于某些语句中的混淆感到抱歉
-
@Root2A 这就是我的想法,是的。如果没有更多的孩子要收割,它会退出处理程序,但是当再次发生 SIGCHLD 时,您将再次进入处理程序。
标签: c unix operating-system signals