如何在Linux C ++中创建多个间隔计时器

时间:2019-06-17 11:50:43

标签: c++ c linux timer

如何在C ++或C语言的Linux中创建两个间隔计时器?我希望第一个间隔计时器调用一个每毫秒递增一个变量的函数,第二个计时器每10毫秒调用另一个函数。

2 个答案:

答案 0 :(得分:0)

您需要使用event loop。例如boost::asio(请参阅前两个计时器教程)libevent。

另一种选择是使用POSIX / Linux API从头开始实现该功能,但这会很快变得混乱,并且需要更多的知识和技能才能做到这一点。

答案 1 :(得分:0)

此解决方案不需要任何单独的线程,第三方库或信号。唯一的警告-根据您的应用程序可能是障碍,也可能不是障碍-主while()循环的每次迭代都必须小于计时器的间隔。

请牢记评论中提到的警告-您不能真正期望获得与RTOS中相同的计时精度-我认为最简单的方法是仅使用clock_gettime() -并将struct timespec的值转换为以毫秒为单位的值。

首先为您的计时器信息定义一个结构:

struct interval_timer {
    unsigned interval;               // interval - in milliseconds
    void (*callback)(const void *);  // callback
    void *callback_arg;              // callback arguments
    unsigned last_triggered;
};

添加一些回调:

static void timer_1_callback(const void *ignore) {
    printf("Timer 1 expired ...\n");
}
static void timer_2_callback(const void *ignore) {
    printf("Timer 2 expired ...\n");
}

创建计时器数组:

static struct interval_timer timers[] = {
    {250, timer_1_callback},
    {1500, timer_2_callback},
};

测试:

int main(int argc, char *argv[]) {
    struct timespec elapsed = {};
    clockid_t clock_id = CLOCK_MONOTONIC;

    size_t timer_count = sizeof(timers) / sizeof(timers[0]);

    printf("Timer tests. %zu timers total ...\n", timer_count);

    while (1) {
        clock_gettime(clock_id, &elapsed);
        long now_ms = timespec_to_ms(&elapsed);
        for (int i = 0; i < timer_count; i++) {
            struct interval_timer *timer = &timers[i];
            if (now_ms - timer->last_triggered > timer->interval) {
                timer->last_triggered = now_ms;
                timer->callback(timer->callback_arg);
            }
        }

        usleep(50);
    }

    return 0;
}

struct timespec转换为毫秒的助手:

static long timespec_to_ms(struct timespec *ts) {
    long ms = ts->tv_sec * 1000;
    ms += ts->tv_nsec / 1000000;
    return ms;
}

替代品

带有setitimer()的信号

您可以使用setitimer()-使用ITIMER_REAL作为时钟ID。每当计时器到期时,这都会生成一个SIGALRM,并且通过安装适当的信号处理程序,您可以设置一个在主while()循环中读取的标志。但是,当您仅可以调用clock_gettime()来检查while()循环的每次迭代的时间时,为什么还要麻烦这个问题并引入与信号相关的问题呢?无论哪种情况:您都必须确保while()循环的频率高于计时器的频率。

使用信号的另一个问题是,很难确定哪个计时器已到期。我不知道将信息传递给信号处理程序的任何直接方法。