Linux定时器使用
在Linux系统中,定时器是实现任务调度、延迟执行或周期性操作的核心工具,无论是系统级服务、应用程序开发还是内核模块设计,定时器都扮演着不可或缺的角色,本文将详细介绍Linux中定时器的使用方法,涵盖内核定时器、用户空间定时器以及常用编程接口,帮助开发者根据实际需求选择合适的定时器方案。

内核定时器
内核定时器是Linux内核提供的一种机制,用于在内核空间中实现延迟执行或周期性任务,其核心特点是基于时间中断,通过jiffies(系统启动以来的时钟节拍数)来管理时间。
-
定时器数据结构
内核定时器的核心数据结构是timer_list,定义在<linux/timer.h>中,主要字段包括:expires:定时器到期时的jiffies值。function:定时器到期时执行的回调函数。data:传递给回调函数的参数。
初始化定时器通常使用
timer_setup()宏,该宏替代了旧版的init_timer(),并支持现代C的特性(如typeof)。 -
定时器操作
- 添加定时器:
add_timer()将定时器加入内核定时器链表,mod_timer()可修改定时器的到期时间并重新调度。 - 删除定时器:
del_timer()用于删除定时器,而del_timer_sync()确保定时器回调函数执行完毕后再返回,适用于多线程环境。 - 定时器回调:回调函数必须符合
void timer_callback(struct timer_list *timer)的签名,且执行时间应尽量短,避免阻塞内核。
- 添加定时器:
-
示例代码
#include <linux/timer.h> #include <linux/module.h> static struct timer_list my_timer; void timer_callback(struct timer_list *timer) { printk(KERN_INFO "Timer expired!\n"); // 可重新添加定时器实现周期性任务 mod_timer(timer, jiffies + msecs_to_jiffies(1000)); } static int __init timer_init(void) { timer_setup(&my_timer, timer_callback, 0); my_timer.expires = jiffies + msecs_to_jiffies(2000); add_timer(&my_timer); return 0; } static void __exit timer_exit(void) { del_timer_sync(&my_timer); } module_init(timer_init); module_exit(timer_exit);
用户空间定时器
在用户空间应用程序中,定时器的实现方式更为多样,主要依赖系统调用或库函数,常见的方案包括sleep()、usleep()、nanosleep()以及高精度定时器库。

-
基础定时函数
sleep(unsigned int seconds):以秒为单位的阻塞式延迟。usleep(useconds_t usec):微秒级延迟(已废弃,推荐nanosleep())。nanosleep(const struct timespec *req, struct timespec *rem):高精度非阻塞延迟,通过timespec结构体指定秒和纳秒。
示例:
#include <time.h> #include <stdio.h> int main() { struct timespec req = {1, 500000000}; // 1.5秒 nanosleep(&req, NULL); printf("Delayed 1.5 seconds\n"); return 0; } -
POSIX定时器
POSIX定时器(timer_create()、timer_settime()等)提供更高精度的周期性任务调度,支持信号通知或线程回调。示例:
#include <signal.h> #include <time.h> #include <stdio.h> static void timer_handler(int sig) { printf("Timer expired\n"); } int main() { struct sigevent sev; struct itimerspec its; timer_t timer_id; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGUSR1; sev.sigev_value.sival_ptr = &timer_id; timer_create(CLOCK_REALTIME, &sev, &timer_id); its.it_value.tv_sec = 2; // 2秒后首次触发 its.it_value.tv_nsec = 0; its.it_interval.tv_sec = 1; // 周期1秒 its.it_interval.tv_nsec = 0; timer_settime(timer_id, 0, &its, NULL); signal(SIGUSR1, timer_handler); while (1); return 0; } -
第三方库
- libevent:事件驱动库,支持定时器、I/O事件等。
- Boost.Asio:C++库,提供跨平台的定时器功能。
定时器选择与注意事项
-
内核 vs 用户空间

- 内核定时器适用于设备驱动、内核模块等需要直接操作硬件或高性能场景。
- 用户空间定时器适合应用程序开发,避免内核态与用户态切换的开销。
-
精度与性能
- 内核定时器的精度受
HZ(时钟节拍频率)影响,通常为1ms-10ms。 - 用户空间可通过
CLOCK_MONOTONIC或CLOCK_HIGHRES提高精度,但需考虑系统负载对定时器准确性的影响。
- 内核定时器的精度受
-
多线程安全
- 内核定时器回调函数中禁用抢占,需避免复杂的同步操作。
- 用户空间定时器需注意线程安全,例如POSIX定时器的信号处理函数应尽量简短。
Linux定时器的使用场景广泛,从内核模块到用户程序均有成熟的解决方案,内核定时器适合底层高性能需求,而用户空间定时器则提供了灵活的编程接口,开发者需根据任务精度、性能要求和开发环境选择合适的定时器机制,并注意多线程、资源释放等细节问题,通过合理使用定时器,可以高效实现各种时间相关的功能,提升系统的可靠性和效率。



















