在 Linux 下,C 语言中可以通过几种方式使用定时器功能。常见的方法包括使用 timer_create
和 setitimer
系列函数来实现定时器。以下是两种常用方法的详细讲解:
1. 使用 timer_create
和 timer_settime
(POSIX 定时器)
POSIX 定时器 API 提供了强大的定时器功能,可以在指定时间间隔后执行回调函数。timer_create
和 timer_settime
允许你创建和管理定时器,提供了更精细的定时控制。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
void timer_handler(union sigval sv) {
printf("Timer expired!\n");
}
int main() {
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
// 设置信号通知方式
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = timer_handler;
sev.sigev_value.sival_ptr = &timerid;
// 创建定时器
if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
perror("timer_create");
exit(1);
}
// 设置定时器超时时间
its.it_value.tv_sec = 5; // 初始定时器超时时间(秒)
its.it_value.tv_nsec = 0; // 初始定时器超时时间(纳秒)
its.it_interval.tv_sec = 5; // 定时器周期(秒)
its.it_interval.tv_nsec = 0; // 定时器周期(纳秒)
// 启动定时器
if (timer_settime(timerid, 0, &its, NULL) == -1) {
perror("timer_settime");
exit(1);
}
// 程序主循环,等待定时器回调
while (1) {
// 可以执行其他任务,定时器回调会在后台处理
sleep(1);
}
return 0;
}
代码说明:
timer_create
:创建一个新的定时器。SIGEV_THREAD
指定定时器到期时会创建一个新线程来调用回调函数。timer_settime
:设置定时器的初始超时(it_value
)和定时器周期(it_interval
)。如果周期为零,定时器将只触发一次。- 回调函数
timer_handler
:当定时器到期时,回调函数会被调用,并打印Timer expired!
。
2. 使用 setitimer
(旧版定时器)
setitimer
也是一个用于设置定时器的函数,但它的控制不如 timer_create
精细,且它依赖于系统信号。setitimer
主要用于实现周期性计时器和一次性定时器。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
void timer_handler(int sig) {
printf("Timer expired!\n");
}
int main() {
struct itimerval timer;
// 安装定时器信号处理程序
signal(SIGALRM, timer_handler);
// 设置定时器:初始超时时间和周期
timer.it_value.tv_sec = 5; // 初始超时(秒)
timer.it_value.tv_usec = 0; // 初始超时(微秒)
timer.it_interval.tv_sec = 5; // 定时器周期(秒)
timer.it_interval.tv_usec = 0; // 定时器周期(微秒)
// 设置定时器
if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
perror("setitimer");
exit(1);
}
// 程序主循环,等待信号
while (1) {
sleep(1); // 主循环
}
return 0;
}
代码说明:
signal(SIGALRM, timer_handler)
:注册一个信号处理程序,当定时器超时后会触发SIGALRM
信号,进而调用timer_handler
函数。setitimer
:设置定时器的超时和周期。ITIMER_REAL
表示与实际时间相关的定时器,触发时会发送SIGALRM
信号。it_value
:定时器第一次超时的时间。it_interval
:定时器周期(如果设置为 0,则为一次性定时器)。
3. 使用 alarm
和 sleep
实现简单定时器
对于不需要高精度的简单定时任务,Linux 也支持使用 alarm
和 sleep
来进行定时。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void timer_handler(int sig) {
printf("Timer expired!\n");
}
int main() {
signal(SIGALRM, timer_handler);
// 设置 5 秒后超时
alarm(5);
// 程序主循环,等待信号
while (1) {
printf("Waiting for timer...\n");
sleep(1); // 模拟其他任务
}
return 0;
}
代码说明:
alarm(5)
:设置一个简单的定时器,5 秒后触发SIGALRM
信号,调用timer_handler
函数。signal(SIGALRM, timer_handler)
:注册一个信号处理函数,当SIGALRM
信号触发时,调用timer_handler
。
总结
timer_create
和timer_settime
:是 POSIX 定时器 API,支持高精度定时,可以设置定时器回调函数,适用于需要精确控制定时的场景。setitimer
:较旧的定时器方式,依赖信号处理,适用于简单的定时任务。alarm
和sleep
:非常基础的定时机制,适用于不需要高精度的简单定时需求。
对于更精细的控制和灵活性,建议使用 timer_create
和 timer_settime
。
发表回复