通过SIGCHLD睡觉

通过SIGCHLD睡觉,c,sleep,sigchld,select-function,C,Sleep,Sigchld,Select Function,我有一个C程序,每分钟轮询一些硬件传感器一次,并将读数添加到数据库中。为了确保读数更接近每分钟(而不是每分钟+开销时间),程序会创建一个子项来完成实际工作,然后在创建另一个子项之前睡眠60秒 我遇到的麻烦是,孩子们的信号干扰了睡眠(60),导致无限的孩子被创造出来,而不是每分钟一个 这就是我一直试图做到的: while(1) { /* Create a child to do the work */ if((pid = fork()) < 0) {

我有一个C程序,每分钟轮询一些硬件传感器一次,并将读数添加到数据库中。为了确保读数更接近每分钟(而不是每分钟+开销时间),程序会创建一个子项来完成实际工作,然后在创建另一个子项之前睡眠60秒

我遇到的麻烦是,孩子们的信号干扰了睡眠(60),导致无限的孩子被创造出来,而不是每分钟一个

这就是我一直试图做到的:

while(1)
{

    /* Create a child to do the work */
    if((pid = fork()) < 0)
    {
        perror("fork");
        exit(1);
    }
    else if(pid > 0)
    {
        /*parent continues*/
        select(0, 0, NULL, NULL, &time);
        claim_children();
        continue;
    }
    /*Now in the child*/
    process_pvs();
}
但出于某种原因,这只适用于while循环中的1次迭代。在那之后,这个项目就不再等待,而是不断地创造孩子


那么,我怎样才能让我的程序最好地做到这一点而不被sigchld打断呢?

你可以简单地围绕它编写代码;检测中断的系统调用,记录时间,并使用逻辑确定是否需要重新进入睡眠状态,如果需要,持续多长时间。

您可以使用

signal(SIGCHLD, SIG_IGN);
这将停止中断,但您需要小心等待所有孩子。通常是一个循环来捕捉它们

while(waitpid(-1, &status, WNOHANG) > 0);

当然,这只有在您没有在其他地方创建其他子进程的情况下才能很好地工作。

在Linux上,我推荐使用timerfd的单线程简单程序。对于
select
调用,可以修改超时结构。我猜您是在Linux上,所以请参阅。有关信号的问题,请参阅,例如:@nos默认情况下,
SIGCHLD
信号被忽略。另一个注意事项。。。如果您阅读,您将看到,如果被信号处理程序中断,它将返回剩余的秒数。总之,阅读手册页总是一个好主意。
信号(SIGCHLD,SIG_IGN)
对于一些较旧的系统来说是不可移植的。谢谢Julian,这样做完全正确。aschepler,这个解决方案只在我的机器上实现,但我肯定会在以后的工作中记住这个建议。
while(waitpid(-1, &status, WNOHANG) > 0);