我在一本电子书中读到, waitpid(-1, &status, WNOHANG) 应该放在 while 循环下,这样如果多个子进程同时退出,它们都会被收获。
我尝试了这个概念,同时创建和终止 2 个子进程,并通过 waitpid 不使用循环来获取它。并且全部都被收获了。
问题是,是否有必要将waitpid置于循环中?
#include<stdio.h>
#include<sys/wait.h>
#include<signal.h>
int func(int pid)
{
if(pid < 0)
return 0;
func(pid - 1);
}
void sighand(int sig)
{
int i=45;
int stat, pid;
printf("Signal caught\n");
//while( (
pid = waitpid(-1, &stat, WNOHANG);
//) > 0){
printf("Reaped process %d----%d\n", pid, stat);
func(pid);
}
int main()
{
int i;
signal(SIGCHLD, sighand);
pid_t child_id;
if( (child_id=fork()) == 0 ) //child process
{
printf("Child ID %d\n",getpid());
printf("child exiting ...\n");
}
else
{
if( (child_id=fork()) == 0 ) //child process
{
printf("Child ID %d\n",getpid());
printf("child exiting ...\n");
}
else
{
printf("------------Parent with ID %d \n",getpid());
printf("parent exiting ....\n");
sleep(10);
sleep(10);
}
}
}
Yes.
好的,我会详细说明。
每次调用 waitpid 都会获得一个且只有一个孩子。由于您将调用放入信号处理程序中,因此无法保证第二个子处理程序会在您完成执行第一个信号处理程序之前退出。对于两个进程来说,这是可以的(待处理信号将在您完成时处理),但对于更多进程,可能是两个子进程将完成,而您仍在处理另一个进程。由于信号没有排队,您将错过通知。
如果发生这种情况,你将无法收获所有的孩子。为了避免这个问题,引入了循环建议。如果您想看到这种情况发生,请尝试与更多的孩子一起进行测试。你跑得越多,你就越有可能发现问题。
抛开这个问题,我们来谈谈其他一些问题。
首先,您的信号处理程序调用printf
。这是一个主要的禁忌。很少有函数是信号处理程序安全的,并且printf
绝对不是一个。您可以尝试使信号处理程序更安全,但更明智的方法是放入仅设置标志的信号处理程序,然后执行实际的操作wait
调用主程序的流程。
由于您的主要流程通常是调用 select/epoll,因此请确保查找pselect
and epoll_pwait
,并了解它们的作用以及为什么需要它们。
更好(但特定于 Linux),请查找signalfd
。您可能根本不需要信号处理程序。
编辑添加:
该循环不会改变两个信号传递合并到一个处理程序调用中的事实。它所做的就是这个调用处理所有待处理的事件。
当然,一旦出现这种情况,你must use WNOHANG
。导致信号合并的相同工件也可能导致您处理尚未传递信号的事件。
如果发生这种情况,那么一旦您的第一个信号处理程序存在,它将再次被调用。然而,这一次,不会有待处理的事件(因为事件已经被循环提取)。如果您不指定WNOHANG
, your wait
阻塞,程序将无限期地卡住。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)