gpt4 book ai didi

c - 如何使 C 计时器在 Linux 中的特定系统时间到期

转载 作者:太空狗 更新时间:2023-10-29 11:14:07 25 4
gpt4 key购买 nike

我试图创建一个依赖于系统时钟的计时器。这意味着当系统时间改变时,它也应该影响这个计时器的到期。所以我想,创建一个基于 CLOCK_REALTIME 的计时器应该做的伎俩。但是当这个定时器在 60 秒后过期并且当我将系统时钟提前 32 秒(使用 date 命令)时,定时器恰好在 60 秒后过期。它没有提前 32 秒过期。

所以我计算了 2 个定时器到期之间 CLOCK_REALTIME 和 CLOCK_MONOTONIC 时钟耗时。它显示 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这告诉

All implementations support the system-wide real-time clock, which is identified by CLOCK_REALTIME. Its time represents seconds and nanoseconds since the Epoch. When its time is changed, timers for a relative interval are unaffected, but timers for an absolute point in time are affected.

这会是这种行为的原因吗?
我在这里做错了什么/遗漏了什么?
有什么方法可以使计时器在特定系统时间到期?

最佳答案

timer_settime 的联机帮助页中可以找到相同的规则,并有一些额外的解释:

By default, the initial expiration time specified in new_value->it_value is interpreted relative to the current time on the timer's clock at the time of the call. This can be modified by specifying TIMER_ABSTIME in flags, in which case new_value->it_value is interpreted as an absolute value as measured on the timer's clock; that is, the timer will expire when the clock value reaches the value specified by new_value->it_value. If the specified absolute time has already passed, then the timer expires immediately, and the overrun count (see timer_getoverrun(2)) will be set correctly.

If the value of the CLOCK_REALTIME clock is adjusted while an absolute timer based on that clock is armed, then the expiration of the timer will be appropriately adjusted. Adjustments to the CLOCK_REALTIME clock have no effect on relative timers based on that clock.

是的,你一直在设置一个相对定时器,所以它忽略了对系统时间的调整。

您可以尝试以下方法:

struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);

struct itimerspec its;
its.it_value.tv_sec = ts.tv_sec + 1;
its.it_value.tv_nsec = ts.tv_nsec;
its.it_interval.tv_sec = 60;
its.it_interval.tv_nsec = 0;
timer_settime(timerID, TIMER_ABSTIME, &its, NULL);

关于c - 如何使 C 计时器在 Linux 中的特定系统时间到期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25152274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com