【发布时间】:2014-08-06 04:31:43
【问题描述】:
我试图创建一个依赖于系统时钟的计时器。这意味着当系统时间更改时,它也会影响此计时器的到期。所以我想,创建一个基于CLOCK_REALTIME 的计时器应该可以解决问题。但是,当这个计时器在 60 秒后到期并且当我将系统时钟提前 32 秒(使用 date 命令)时,计时器正好在 60 秒后到期。它没有提前 32 秒过期。
所以我计算了 CLOCK_REALTIME 和 CLOCK_MONOTONIC 时钟在 2 个定时器到期之间经过的时间。它显示 CLOCK_REALTIME 为 92 秒,CLOCK_MONOTONIC 为 60 秒,这让我感到惊讶的是,基于 CLOCK_REALTIME 的计时器没有查找系统时钟更改。谁能解释一下这种行为?
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <sys/time.h>
timer_t timerID;
struct timespec rt1, rt2, mt1, mt2;
void TimerCalback()
{
clock_gettime(CLOCK_REALTIME, &rt1);
clock_gettime(CLOCK_MONOTONIC, &mt1);
printf("%lu sec elapsed for CLOCK_REALTIME\n", rt1.tv_sec - rt2.tv_sec);
printf("%lu sec elapsed for CLOCK_MONOTONIC\n", mt1.tv_sec - mt2.tv_sec);
rt2 = rt1;
mt2 = mt1;
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf("REALTIME Timer Expired at %s\n", asctime (timeinfo));
}
void CreateTimer()
{
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = TimerCalback;
sigemptyset(&sa.sa_mask);
sigaction(SIGRTMIN, &sa, NULL);
struct sigevent te;
memset(&te,0,sizeof(struct sigevent));
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = SIGRTMIN;
te.sigev_value.sival_ptr = &timerID;
timer_create(CLOCK_REALTIME, &te, &timerID);
struct itimerspec its;
its.it_value.tv_sec = 1;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 60;
its.it_interval.tv_nsec = 0;
timer_settime(timerID, 0, &its, NULL);
}
void main()
{
CreateTimer();
while(1)
{
usleep(1);
}
}
我得到了这个输出。第一次到期后,我提高了系统时钟。
$ ./realtimeTimer
1407240463 sec elapsed for CLOCK_REALTIME
17747 sec elapsed for CLOCK_MONOTONIC
REALTIME Timer Expired at Tue Aug 5 17:37:43 2014
92 sec elapsed for CLOCK_REALTIME
60 sec elapsed for CLOCK_MONOTONIC
REALTIME Timer Expired at Tue Aug 5 17:39:15 2014
后来在网上搜索,我偶然发现了this man page,这告诉了我
所有实现都支持系统范围的实时时钟,由 CLOCK_REALTIME 标识。它的时间表示自纪元以来的秒和纳秒。 当其时间改变时,相对间隔的计时器不受影响,但绝对时间点的计时器受到影响。
这可能是这种行为的原因吗?
我在这里做错了什么/错过了什么?
有没有办法让计时器在特定的系统时间到期?
【问题讨论】: