linux 内核定时器

时间:2022-11-12 23:33:03
#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);
}