c - C语言中启动多个定时器并知道哪一个已经结束

标签 c linux timer signals

我需要能够同时启动多个计时器,并具体了解计时器是否已停止或仍在运行。

#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/

相关文章:

计算将字符串分成至少 1 个元音的 3 个部分的可能性数量

c - 为什么 strcpy 在数组大小不可变时工作,C

linux - Mips 和 mipsel 工具链为同一可执行文件提供不同的堆栈信息

linux - 具有作业控制的 Bash 进程替换后台

timer - MSP 430G2553 使用 Timer_A 在比较模式下进行采样

c - 使用指针修改字符串

c - 为什么这个 SDL2 程序变慢了?

linux - 在 bash 脚本的 until 循环中验证多个表达式

java - 如何在 Swing 中更新 JLabel?

java - 启动计时器后向普罗米修斯直方图添加标签