我需要能够同时启动多个计时器,并具体了解计时器是否已停止或仍在运行。
#define RESEND_TIMEOUT 5
void timer_set_timeout(timer_t * timer, uint32_t timeout);
void timer_start(timer_t * timer);
bool timer_complete(timer_t * timer);
void signal_handler(int sig, siginfo_t *si, void *uc);
int main() {
timer_t resend_timer;
printf("starting timer\n");
timer_start(&resend_timer);
timer_set_timeout(RESEND_TIMEOUT);
while(1) {
if (timer_complete(&resend_timer))
break;
}
}
void timer_set_timeout(timer_t * timer, uint32_t timeout)
{
struct itimerspec it_val;
it_val.it_value.tv_sec = timeout;
it_val.it_value.tv_nsec = 0;
it_val.it_interval.tv_sec = 0;
it_val.it_interval.tv_nsec = 0;
if (timer_settime(*timer, 0, &it_val, NULL) == -1) {
errExit("Could not set timeout");
}
}
void timer_start(timer_t * timer)
{
struct sigaction sa;
struct sigevent sev;
// establish signal handler
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = signal_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
errExit("Failed to establish signal handler");
// create timer
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = timer;
if(timer_create(CLOCK_MONOTONIC, &sev, timer) == -1) {
errExit("Could not start timer");
}
}
// return true if timer ended
bool timer_complete(timer_t * timer)
{
if(timer_getoverrun(*timer) == 0)
return false;
else
return true;
}
void signal_handler(int sig, siginfo_t *si, void *uc)
{
printf("Timer ran out!\n");
signal(sig, SIG_IGN);
}
信号处理程序在5秒后运行,但我无法使用timer_complete知道计时器是否已结束。 我尝试过: int timer_gettime(timer_t timerid, struct itimerspec *curr_value) 但我不知道如何传递 curr_value。我尝试声明一个 itimerspec,但它给出的结果与 getoverrun 相同。
我还尝试使用标记 TIMER_ABSTIME 来设置timer_settime,但计时器由于某种原因立即到期。
最佳答案
您误解了计时器已完成的含义。
从一开始,计时器就有 2 组值。一组是 future 定时器响起的时间;另一个是间隔值,用于在定时器关闭后重新加载第一组。如果使用第一组但间隔值设置为零,那么根据定义,它是一次性计时器。如果间隔值非零,那么计时器将永久重新加载并触发,直到您将其关闭。您可以通过使用 timer_settimer
将所有值设置为零来关闭它。
所以在你的timer_complete中应该看起来像这样:
// return true if timer ended
bool timer_complete(timer_t * timer)
{
struct itimerspec its;
if (timer_gettime(*timer, &its) == -1)
{
perror("timer_settime");
exit(1);
}
If ((its.it_value.tv_sec == 0) &&
(its.it_value.tv_nsec == 0) &&
(its.it_interval.tv_sec == 0) &&
(its.it_interval.tv_nsec == 0))
return true;
else
return false;
}
超支是另一种动物。基本上,操作系统不会多次对计时器信号进行排队,即使是实时信号,因为可能太多了。 Overrun 告诉您在程序收到信号之前发生了多少次计时器关闭(可能是排队信号)的情况。
关于c - C语言中启动多个定时器并知道哪一个已经结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19782203/