Linux内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,调度函数在运行过一次后就不会再运行了(相当于自动注销),但可以通过在被调度的函数中重新调度自己来周期运行。
(1)jiffies定时器,HZ=100,精度只能达到10ms,已验证
#include
#include
static struct timer_list ms_timer;
static void ms_timer_handler(void)
{
printk("DO_DEBUG----------->%s\n",__func__);
ms_timer.expires=jiffies+msecs_to_jiffies(10);
ms_timer.function=&ms_timer_handler;
add_timer(&ms_timer);//循环执行自己
}
static int32_t xxx_init(void)
{
init_timer(&ms_timer); //DO-->初始化定时器
ms_timer.expires=jiffies+msecs_to_jiffies(10); //DO-->定义中断时间:10ms进入中断
ms_timer.function=&ms_timer_handler; //DO-->定义定时器中断处理函数
add_timer(&ms_timer); //DO-->增加注册定时器,使定时器生效
}
移除定时器,用del_timer_sync(&ms_timer)。以上ms_timer_handler的内容,可用
printk("DO_DEBUG----------->%s\n",__func__);
mod_timer(&ms_timer,jiffies+msecs_to_jiffies(10));代替
(2)hrtimer高精度定时器,可做到ns级。如下代码可跑,但是会死机。
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode);
extern void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,enum hrtimer_mode mode);
extern int hrtimer_cancel(struct hrtimer *timer);
#define BAT_MS_TO_NS(x) (x * 1000 * 1000)
static struct hrtimer charger_hv_detect_timer;
void __exit kernel_test_exit()
{
hrtimer_cancel(&charger_hv_detect_timer);
printk("module out kernel_test_exit \r\n");
}
enum hrtimer_restart charger_hv_detect_sw_workaround(struct hrtimer *timer)
{
printk("charger_hv_detect_sw_workaround \n");
return HRTIMER_RESTART;
}
int __init kernel_test_init()
{
ktime_t ktime;
ktime = ktime_set(0, BAT_MS_TO_NS(2000));
hrtimer_init(&charger_hv_detect_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
charger_hv_detect_timer.function = charger_hv_detect_sw_workaround;
hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL);
printk("module in kernel_test_init \r\n");
return 0;
}
module_init(kernel_test_init);
module_exit(kernel_test_exit); 使用extern申明的原因是,未加之前insmod提示-1 Unknown symbol in module,使用dmesg|tail查看,提示
[ 1644.432578] helloworld: module license 'unspecified' taints kernel.
[ 1644.432580] Disabling lock debugging due to kernel taint
[ 1644.432624] helloworld: Unknown symbol hrtimer_init (err 0)
[ 1644.432630] helloworld: Unknown symbol hrtimer_start (err 0)
[ 1644.432638] helloworld: Unknown symbol hrtimer_cancel (err 0)
但是通过cat /proc/kallsyms打印内核符号表是可以找到这三个系统系统函数的,所以加了extern申明调用EXPORT_SYMBOL函数。但是光加这个还不够,提示taint还要解决模块的License问题,所以加上再MODULE_LICENSE。最终可以insmod成功,提示
[ 2058.475797] charger_hv_detect_sw_workaround
[ 2058.475800] charger_hv_detect_sw_workaround
[ 2058.475802] charger_hv_detect_sw_workaround