2014-11-04 96 views
0

我想实现一个后台用户空间程序,它将在Linux中每100ms执行一次各种任务和计算。我可以通过在Linux中使用报警信号来实现这一点,下面的结构是我实现间隔计时器的方式。在Linux中使用C++实现低开销间隔计时器

void timer_handler (int signum){ 
    printf("In timer handler!\n"); 
} 

int main(){ 

    struct sigaction s_action; 
    struct itimerval timer; 

    /* Set Up a Timer */ 
    /* Install timer_handler as the signal handler for SIGVTALRM. */ 
    memset (&s_action, 0, sizeof (s_action)); 
    s_action.sa_handler = &timer_handler; 
    sigaction (SIGVTALRM, &s_action, NULL); 

    /* Timer configuration for 100ms */ 
    timer.it_value.tv_sec = 0; 
    timer.it_value.tv_usec = 100000; 
    timer.it_interval.tv_sec = 0; 
    timer.it_interval.tv_usec = 100000; 

    /* Set up the timer */ 
    setitimer (ITIMER_VIRTUAL, &timer, NULL); 

    while(1); 
} 

但是,由于无限循环,这种方法似乎不是最佳的方法(就性能而言)。它显着增加了CPU利用率。一旦它开始在后台运行,我的其他程序的性能会下降15%。

我最想要的是有一个程序,除非发生定时器中断,否则会保持睡眠状态。多线程似乎是一种选择,但我对这个主题并不很有经验。我将不胜感激任何有关如何以最小的开销实施此类计划的建议或指示。

+1

如果你想让你的程序进入睡眠状态,为什么不调用sleep()? – 2014-11-04 20:00:08

+0

我首先尝试睡眠,但没有奏效。使用sleep()或nanosleep(),我的定时器处理程序似乎从未触发。我从警报(2)手册页读取了sleep()可能会干扰SIGALRM信号。 – jake 2014-11-04 21:59:26

回答

0

阅读time(7),​​,timerfd_create(2)poll(2)nanosleep(2)Advanced Linux Programming

您的信号处理程序不正确(它不应该调用printf;它可能是write)。

你可以有

while(1) poll(NULL, 0, 1); 

但可能与timerfd_create初始化文件描述符使用poll真实的事件循环应该会更好。

我假设你当然相信每个周期性任务的持续时间要比这个周期少得多。 (例如,每个任务需要不超过50毫秒但是具有100毫秒的时间)。

+1

我认为我的问题主要是由于我用setitimer使用的标志(ITIMER_VIRTUAL),它只在进程处于活动状态时才计数。将它切换到ITIMER_REAL并按照您的建议轮询NULL文件描述符似乎会导致100ms间隔的非常低的开销。也非常感谢参考资料。 – jake 2014-11-04 22:35:45