间隔定时器不按指定的时间间隔触发信号

问题描述 投票:0回答:2

我想每2秒调用一次timer_handler函数,无论timer_handler函数的执行时间如何,这里都是我的代码

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

void timer_handler (int signum)
{
 static int count = 0;
 sleep(1);
 printf ("timer expired %d times %d signum \n", ++count, signum);
}

int main ()
{
 struct sigaction sa;
 struct itimerval timer;

 /* timer_handler as the signal handler for SIGVTALRM. */
 memset (&sa, 0, sizeof (sa));
 sa.sa_handler = &timer_handler;
 sigaction (SIGVTALRM, &sa, NULL);

 /* Configure the timer to expire after 2000 msec... */
 timer.it_value.tv_sec = 2;
 timer.it_value.tv_usec = 0;
 /* ... and every 2000 msec after that. */
 timer.it_interval.tv_sec = 2;
 timer.it_interval.tv_usec = 0;
 /* Start a virtual timer. It counts down whenever this process is
   executing. */
 setitimer (ITIMER_VIRTUAL, &timer, NULL);
 /* Do busy work. */
 while (1);
}

按照上面的代码,它应该每两秒打印一次timer expired 1 times 26 signum,但每隔3秒打印一次,包括睡眠时间,所以我想每隔2秒调用一次该函数。我不知道我在哪里做错如果其他图书馆能够做到这一点请告诉我知道谢谢

c timer sleep setitimer
2个回答
1
投票

为什么不使用挂钟时间?

这样做

  • 安装SIGALRM的信号处理程序而不是SIGVTALRM
  • 指定ITIMER_REAL而不是ITIMER_VIRTUAL

不相关但重要:信号处理程序可能只调用异步信号安全功能。 printf()不是其中之一。 For a list of the latter click here and scroll down


0
投票

在信号处理程序中调用:sleep(1)在处理信号时增加了额外的秒数。额外的秒数不是流程执行时间的一部分。

从信号处理程序中删除:

sleep(1);

关于:

setitimer (ITIMER_VIRTUAL, &timer, NULL);

因为你想看到每2秒执行一次信号处理程序,所以使用的正确计时器是:ITIMER_REAL而不是ITIMER_VIRTUAL。这将导致测量“墙上的时钟”时间,而不是测量的“过程运行”时间。

强烈建议让信号处理程序只设置一个标志。然后main函数中的'do nothing'循环检查该标志,重置标志,然后调用printf()`要正确完成此操作,在没有'race'条件下,使用互斥锁/主要和信号处理程序将锁定互斥锁,修改标志,然后解锁互斥锁。

© www.soinside.com 2019 - 2024. All rights reserved.