如何实现定时循环?

时间:2014-05-09 06:31:26

标签: c embedded-linux

我需要每秒执行1000次代码。 我想做点什么:

set up interval timer
while (1)
{
   wait for timer
   do something
}

我的尝试看起来像

// Create timer
timer_t timerid;
struct sigevent sev;

sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;

if (timer_create(CLOCK_REALTIME, &sev, &timerid))
{
perror("timer_create");
exit(1);
}

// Every one mSec (10^6 nsec)
struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1000000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 1000000;
if (timer_settime(timerid, 0, &its, NULL))
{
perror("timer_settime");
exit(1);
}

// Create mask to wait for SIGUSR1
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);

while (1)
{
int sig;

// Wait for the timer: Do this loop once per millisecond
sigwait(&set, &sig);

    (do something)
}

当我尝试这个时,我只是在控制台上获得“用户定义的信号1”并且我的程序退出。这并不奇怪,因为这是信号的默认操作。如果我使用sigaction(2)将信号设置为SIG_IGN,我永远不会找到我的(做某事)。

我认为我需要对sigaction(2)做一些事情,但我没有看到“传递信号”的选项。我不想忽略信号,或者执行默认操作,或者调用函数。 什么是实现目标的最佳方式?

或者我可以放弃并将我的(做某事)放在一个函数中: - )

编辑:我实现了timerfd的想法,它似乎正在运作。到下一个bug ...

2 个答案:

答案 0 :(得分:4)

由于您已使用embedded-linux标记了问题,因此我认为可移植性不是问题。在这种情况下,您可能需要查看timerfd。它允许您使用select(2) / poll(2)来接收您的计时器事件。它还可以更容易地将间隔计时器与其他事件源(如文件描述符)结合使用。

答案 1 :(得分:0)

我认为你应该按照n.m的建议设置一个真正的信号处理程序。查看man sigaction以获取您的Linux版本。您可以在信号处理程序中调用do_something(并等待其他程序终止程序),或者只返回一个处理程序并保持sigwait逻辑。