#include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO */ #include <linux/init.h> /* Needed for the macros */ #include <linux/jiffies.h> #include <linux/time.h> #define MAXRUNS 50 #include <linux/hrtimer.h> static volatile int runcount = 0; //~ static struct timer_list my_timer; static unsigned long period_ms; static unsigned long period_ns; static ktime_t ktime_period_ns, kt_now, kt_now2; static struct hrtimer my_hrtimer, my_hrtimer2; static ktime_t sum; //~ static void timer_timer_function(unsigned long data) static enum hrtimer_restart timer_callback(struct hrtimer *timer) { //kt_now1 = hrtimer_cb_get_time(&my_hrtimer); //printk(KERN_INFO"timer1:%lld\n", ktime_to_ns(kt_now1)); //int ret_overrun; /*runcount++; //设置时钟2到期时间,启动时钟2 if(runcount < MAXRUNS)*/ { ktime_period_ns = ktime_set(0, ((unsigned long)1E3L)); hrtimer_start(&my_hrtimer, ktime_period_ns, HRTIMER_MODE_REL); } //读取时钟的当前过期时间 printk("one!\n"); // kt_now = hrtimer_cb_get_time(&my_hrtimer); //从kt_now推迟多个ktime_period_ns到未来新的过期时间 // hrtimer_forward(&my_hrtimer, kt_now, ktime_period_ns); /*kt_now = hrtimer_cb_get_time(&my_hrtimer); //读取延迟后时钟时期 kt_after = hrtimer_cb_get_time(&my_hrtimer); //计算推迟的间隔 sub = ktime_sub(kt_after, kt_now); sum = ktime_add(sum, sub); */ return HRTIMER_NORESTART; } static enum hrtimer_restart timer2_callback(struct hrtimer *timer) { kt_now2 = hrtimer_cb_get_time(&my_hrtimer2); printk(KERN_INFO"timer2:%lld\n", ktime_to_ns(kt_now2)); /*ktime_t kt_now; runcount++; //设置时钟2到期时间,启动时钟2 if(runcount < MAXRUNS) { ktime_period_ns = ktime_set(0, ((unsigned long)1E3L)); hrtimer_start(&my_hrtimer, ktime_period_ns, HRTIMER_MODE_REL); } //因为重新设置了时钟,因此需要重新启动时钟*/ return HRTIMER_NORESTART; } static int __init timer_init(void) { struct timespec tp_hr_res; period_ms = 250/HZ; hrtimer_get_res(CLOCK_MONOTONIC, &tp_hr_res); printk(KERN_INFO"Init timer: %d ; HZ: %d ; 1/HZ (ms): %ld ; hrres: %lld.%.9ld\n", runcount, HZ, period_ms, (long long)tp_hr_res.tv_sec, tp_hr_res.tv_nsec ); //初始化自己的时钟 hrtimer_init(&my_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); //hrtimer_init(&my_hrtimer2, CLOCK_MONOTONIC, HRTIMER_MODE_REL); //设置回调函数 my_hrtimer.function = &timer_callback; //my_hrtimer2.function = &timer2_callback; //ms宽展成ns,乘10^6 period_ns = ((unsigned long)1E4L ); //设置过期时间,函数参数secs,nsecs ktime_period_ns = ktime_set(0, (unsigned long)1E4L); printk(KERN_INFO"ktime_period_ns:%ld\n", ktime_period_ns); hrtimer_start(&my_hrtimer, ktime_period_ns, HRTIMER_MODE_REL); /*ktime_period_ns = ktime_set(0, (unsigned long)1.1E4L); printk(KERN_INFO"ktime_period_ns:%ld\n", ktime_period_ns); hrtimer_start(&my_hrtimer2, ktime_period_ns, HRTIMER_MODE_REL);*/ return 0; } static void __exit timer_exit(void) { int ret_cancel = 0; //时钟1 //循环检测是不是在执行回调函数 while( hrtimer_callback_running(&my_hrtimer) ) { ret_cancel++; } //不为0,则等待回调函数执行了 if (ret_cancel != 0) { printk(KERN_INFO " timer Waited for hrtimer callback to finish (%d)\n", ret_cancel); } //检测时钟是不是在红黑树中,或者回调函数正在执行 if (hrtimer_active(&my_hrtimer) != 0) { //取消时钟 ret_cancel = hrtimer_cancel(&my_hrtimer); printk(KERN_INFO " timer active hrtimer cancelled: %d (%d)\n", ret_cancel, runcount); } //检测时钟是不是在一个队列中 if (hrtimer_is_queued(&my_hrtimer) != 0) { //取消时钟 ret_cancel = hrtimer_cancel(&my_hrtimer); printk(KERN_INFO " timer queued hrtimer cancelled: %d (%d)\n", ret_cancel, runcount); } /* //时钟2 while( hrtimer_callback_running(&my_hrtimer2) ) { ret_cancel++; } //不为0,则等待回调函数执行了 if (ret_cancel != 0) { printk(KERN_INFO " timer Waited for hrtimer callback to finish (%d)\n", ret_cancel); } //检测时钟是不是在红黑树中,或者回调函数正在执行 if (hrtimer_active(&my_hrtimer2) != 0) { //取消时钟 ret_cancel = hrtimer_cancel(&my_hrtimer2); printk(KERN_INFO " timer active hrtimer cancelled: %d (%d)\n", ret_cancel, runcount); } //检测时钟是不是在一个队列中 if (hrtimer_is_queued(&my_hrtimer2) != 0) { //取消时钟 ret_cancel = hrtimer_cancel(&my_hrtimer); printk(KERN_INFO " timer queued hrtimer cancelled: %d (%d)\n", ret_cancel, runcount); } printk(KERN_INFO"timer sub:%ld\n", ktime_to_ns(ktime_sub(kt_now2, kt_now1)));*/ printk(KERN_INFO "Exit timer\n"); } module_init(timer_init); module_exit(timer_exit); MODULE_LICENSE("GPL");
bbbb
延时示例
signed long __sched schedule_timeout(signed long timeout) { struct timer_list timer; unsigned long expire; switch (timeout) { case MAX_SCHEDULE_TIMEOUT: //无限期睡眠 schedule(); goto out; default: if (timeout < 0) { current->state = TASK_RUNNING; goto out; } } //超时时间 expire = timeout + jiffies; //初始化一个timer定时器 参数current task,//设定定时器,到时启动process_timeout函数 setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); schedule(); del_singleshot_timer_sync(&timer); /* Remove the timer from the object tracker */ destroy_timer_on_stack(&timer); timeout = expire - jiffies; out: return timeout < 0 ? 0 : timeout; } static void process_timeout(unsigned long __data) { //唤醒被睡眠的任务 wake_up_process((struct task_struct *)__data); }