Linux 内核 timer_setup_on_stack
接口使用与注意事项
timer_setup_on_stack
是 Linux 内核中用于在栈上设置定时器的函数。与 timer_setup
类似,它初始化一个定时器,但专门用于栈上定时器的使用场景。相比普通定时器,栈上定时器的生命周期仅限于当前函数调用栈,因此需要特别注意生命周期管理,以避免内存访问错误。
函数原型
void timer_setup_on_stack(struct timer_list *timer, void (*callback)(struct timer_list *), unsigned int flags);
timer
: 指向栈上的struct timer_list
实例。callback
: 定时器触发时调用的回调函数。flags
: 定时器的标志位(一般为 0)。
示例代码
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example for timer_setup_on_stack");
static void stack_timer_callback(struct timer_list *t)
{
pr_info("Stack timer callback triggered! jiffies = %lu\n", jiffies);
}
static int __init stack_timer_example_init(void)
{
struct timer_list timer;
unsigned long delay = msecs_to_jiffies(500); // 500 毫秒延迟
// 初始化栈上定时器
timer_setup_on_stack(&timer, stack_timer_callback, 0);
// 设置定时器触发时间
timer.expires = jiffies + delay;
// 添加定时器
add_timer(&timer);
pr_info("Stack timer added. jiffies = %lu\n", jiffies);
// 延时等待定时器触发
msleep(600);
// 删除定时器(需要确保定时器已经触发)
del_timer_sync(&timer);
// 释放栈上定时器
destroy_timer_on_stack(&timer);
pr_info("Stack timer deleted and destroyed.\n");
return 0;
}
static void __exit stack_timer_example_exit(void)
{
pr_info("Stack timer example module exited.\n");
}
module_init(stack_timer_example_init);
module_exit(stack_timer_example_exit);
关键点说明
-
定时器初始化:
使用timer_setup_on_stack
初始化栈上定时器,指定回调函数和标志位。 -
触发时间设置:
使用timer.expires = jiffies + delay
指定触发时间。 -
添加定时器:
调用add_timer(&timer)
将定时器加入内核的定时器链表。 -
删除定时器:
调用del_timer_sync(&timer)
确保定时器完成后再移除,避免回调与删除操作竞争。 -
释放资源:
在栈上使用的定时器必须调用destroy_timer_on_stack(&timer)
以释放相关资源。
注意事项
-
生命周期限制:
栈上定时器的生命周期受限于当前函数栈帧,必须在函数返回前删除并释放定时器。 -
回调安全性:
使用del_timer_sync
确保回调函数执行完毕,避免因回调未完成而导致竞争条件。 -
不建议长期存在:
栈上定时器仅适合短期操作,不应用于长期或跨函数调用的定时任务。 -
线程上下文问题:
确保调用栈上定时器的上下文是安全的,不要在中断上下文中使用。 -
避免内存泄漏:
忘记调用destroy_timer_on_stack
可能导致内核内存泄漏。
适用场景
- 在内核模块中实现临时的、短生命周期的定时操作。
- 不需要长期存在的定时器。
- 希望避免动态分配内存的开销。
timer_setup_on_stack
提供了一种高效的定时器管理方式,但它的使用场景和生命周期管理需要开发者特别小心。对于需要长期存在的定时器,建议使用全局或动态分配的定时器。