间隔计时器未在指定时间间隔触发信号
Interval Timer not firing signal at specified time interval
我想每 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 秒调用一次该函数。
我不知道我哪里做错了
如果任何其他图书馆能够做到这一点,请告诉我
谢谢
为什么不使用挂钟时间?
这样做
- 为
SIGALRM
安装信号处理程序而不是 SIGVTALRM
和
- 指定
ITIMER_REAL
而不是 ITIMER_VIRTUAL
。
无关但重要:信号处理程序只能调用异步信号安全函数。 printf()
不是其中之一。 For a list of the latter click here and scroll down.
信号处理程序中的调用:sleep(1)
为信号处理增加了额外的一秒。这额外的一秒不是进程执行时间的一部分。
从信号处理程序中删除:
sleep(1);
关于:
setitimer (ITIMER_VIRTUAL, &timer, NULL);
由于您希望看到信号处理程序每 2 秒执行一次,因此要使用的正确计时器是:ITIMER_REAL
而不是 ITIMER_VIRTUAL
。这将导致测量 'clock on the wall' 时间而不是测量 'process run' 时间。
强烈建议让信号处理程序只设置一个标志。然后 main 函数中的 'do nothing' 循环检查该标志,重置标志,然后调用 printf()` 要正确完成此操作,在没有 'race' 条件的情况下,使用互斥锁/ main 和信号处理程序将锁定互斥锁,修改标志,然后解锁互斥锁。
我想每 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 秒调用一次该函数。
我不知道我哪里做错了
如果任何其他图书馆能够做到这一点,请告诉我
谢谢
为什么不使用挂钟时间?
这样做
- 为
SIGALRM
安装信号处理程序而不是SIGVTALRM
和 - 指定
ITIMER_REAL
而不是ITIMER_VIRTUAL
。
无关但重要:信号处理程序只能调用异步信号安全函数。 printf()
不是其中之一。 For a list of the latter click here and scroll down.
信号处理程序中的调用:sleep(1)
为信号处理增加了额外的一秒。这额外的一秒不是进程执行时间的一部分。
从信号处理程序中删除:
sleep(1);
关于:
setitimer (ITIMER_VIRTUAL, &timer, NULL);
由于您希望看到信号处理程序每 2 秒执行一次,因此要使用的正确计时器是:ITIMER_REAL
而不是 ITIMER_VIRTUAL
。这将导致测量 'clock on the wall' 时间而不是测量 'process run' 时间。
强烈建议让信号处理程序只设置一个标志。然后 main 函数中的 'do nothing' 循环检查该标志,重置标志,然后调用 printf()` 要正确完成此操作,在没有 'race' 条件的情况下,使用互斥锁/ main 和信号处理程序将锁定互斥锁,修改标志,然后解锁互斥锁。