如何在C ++或C语言的Linux中创建两个间隔计时器?我希望第一个间隔计时器调用一个每毫秒递增一个变量的函数,第二个计时器每10毫秒调用另一个函数。
答案 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()
循环的频率高于计时器的频率。
使用信号的另一个问题是,很难确定哪个计时器已到期。我不知道将信息传递给信号处理程序的任何直接方法。