在寻找sigchild代码时,我有以下代码。在下面的代码中,创建了50个子节点,父进程在sigchild处理程序中等待,直到所有50个子节点都被销毁。
如果我在main的末尾使用while(sleep(1))
,我会得到预期的结果,但如果我用sleep(1)
替换它,那么在所有子进程终止之前,父进程将被阻塞。
int l=0;
/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
/* Wait for all dead processes.
* We use a non-blocking call to be sure this signal handler will not
* block if a child was cleaned up in another part of the program. */
while (waitpid(-1, NULL, WNOHANG) > 0) {
printf(" %d",l++);
}
printf("\nExiting from child :: %d\n",l);
}
int main (int argc, char *argv[])
{
struct sigaction act;
int i;
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
/* Make some children. */
for (i = 0; i < 50; i++) {
switch (fork()) {
case -1:
perror ("fork");
return 1;
case 0:
return 0;
}
}
/* Wait until we get a sleep() call that is not interrupted by a signal. */
while (sleep(1)) {
}
// sleep(1);
printf("\nterminating\n");
return 0;
}
答案 0 :(得分:0)
答案 1 :(得分:0)
在寻找sigchild代码时,我有以下代码。在 创建了50个以下子代码,父进程等待 直到所有50个孩子都被摧毁之前,sigchild处理程序。
不,它没有。如果没有人退出,waitpid WNOHANG将会失败。并且无法保证在执行处理程序期间所有子项都退出(或将退出)。
即使只是睡觉(1),也无法保证任何孩子都能设法退出,但实际上大多数孩子都会退出。
睡觉是一种根本错误的方法。既然你知道你创造了多少个孩子,那么你应该等待所有孩子完成它们。例如,你可以在每次收获某些东西时减少现有孩子的计数器并等待它变为0。根据真实程序的样子,你可能不想在第一时间使用处理程序:只需要循环结束,但没有WNOHANG。
我还要对此发表评论:
/ *等待所有死进程。 *我们使用非阻塞调用来确保此信号处理程序不会 *阻止孩子在该计划的另一部分被清理。 * /
您无法混合信号处理程序并自行等待。您冒险从等待它的其他代码中抢夺进程,然后会发生什么?
这是一个设计错误。 fork / exit行为必须统一或分散。