我尝试使用以下(Will wait and waitpid block SIGCHLD and unblock it when they return in Linux?)来回答我的问题 . 链接的解决方案让我了解下面的理解 . 那为什么会弄错?
鉴于以下内容:
- 处理程序
void sig_child(int sig)
{
signal(SIGCHLD, sig_child);
if (sig == SIGCHLD)
{
int status;
pid_t num;
while ((num = waitpid(WAIT_ANY, &status, WNOHANG)) > 0)
{
}
if (num == -1 && errno != ECHILD)
{
// We shouldn't reach here
assert(0);
}
}
主要的模糊:
if (pidnum)
{ //Some work
int status;
pid_t num = waitpid(pidnum, &status, 0);
// Some work
}
我认为应该发生以下情况:
1)主代码(在第二个模糊中)调用waitpid
2)引发SIG_CHLD,因此控制转移到信号处理程序
3)信号处理程序从信号处理程序中删除已终止的子进程,获取其状态信息
4)当控制转回主代码(第二个模糊)时,由于进程的子进程已从进程表中删除,因此num应设置为-1
实际上,发生了以下情况(我使用了一些现在被删除以跟踪流程的打印语句),这与我上面的理解相矛盾:
1)主要的模糊到达waitpid
2)引发SIG_CHLD,因此控制转移到处理程序
3)num设置为-1,errno设置为ECHILD
4)控制返回到主模糊,其中num被赋予之前分叉的孩子的pid .
1 回答
你正在做两个具有重叠标准的
waitpid
,抱怨一个人 grab 了你的过程而另一个人认为没有办法解决这个特殊情况 .我看到它的方式,你有两个解决方案的途径 . 一种是使用不重叠的
waitpid
标准 . 问题是,很难看出如何创建这样的案例 .更合理的解决方案是在主循环中只有一个
waitpid
. 等待检查报告的pid,并以两种不同的方式处理它 . 如果它是主程序的孩子,做一件事 . 如果它是您正在运行的后台任务之一,请执行另一个(或者,在您的情况下,不执行任何操作) .如果你不能,无论出于何种原因,在主循环内部处理后台进程的退出时,只需在执行主等待时阻止
SIGCHLD
.在任何情况下,请始终牢记
SIGCHLD
是一个非排队信号 . 这意味着您永远无法确保调用信号处理程序的次数与运行的wait
次数之间存在1:1的关系 .