2012-10-08 46 views
2

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

我遇到的麻烦是来自孩子的SIGCHLD正在中断睡眠(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(); 
} 

我还听说过那个select()方法可以用来实现我后通过执行以下操作:

struct timeval time; 

time.tv_sec = 60; 
time.tv_usec = 0; 

select(0, 0, 0, 0, time); 

但由于某种原因,这只适用于while循环中的1次迭代。之后,该计划不会等待,并不断创建孩子。

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

+2

在Linux上,我推荐使用timerfd的单线程简单程序。 –

+1

对于'select'调用,可以修改超时结构。我想你在Linux上,所以看[手册页](http://linux.die.net/man/2/select)。 –

+0

有关信号的问题,请参阅['sigprocmask'](http://linux.die.net/man/2/sigprocmask)。 –

回答

1

可以忽略与

signal(SIGCHLD, SIG_IGN); 

这孩子信号将停止中断,但你必须要小心,你等待所有的孩子。通常是一个循环来捕捉它们。

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

只有当您在其他地方没有制作其他子进程时,这才有效。

+1

'signal(SIGCHLD,SIG_IGN)'不适用于某些较旧的系统。 – aschepler

+0

谢谢朱利安,那完全正确的工作。这个解决方案只能在我的机器上实现,但我将在未来的作品中牢记这一建议。 –

2

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