内核软定时器

linux内核软件定时器
1.linux内核描述定时器使用的数据结构
struct timer_list {
    unsigned long expires; //定时器的超时时间,例如如果设置超时时间的间隔为5秒;expires = jiffies + 5*HZ
    void (*function)(unsigned long);//定时器的处理函数,当超时时间到期,内核就会执行定时器的处理函数,定时器到期内核会将定时器删除,也就是说定时器的处理函数只执行一次;
    unsigned long data; //给定时器处理函数传递的参数,一般传递指针
};

如何使用内核定时器?
1.分配定时器对象
   struct timer_list mytimer;
2.初始化定时器对象
   init_timer(struct timer *timer);
   函数功能:初始化定时器
   参数:分配的定时器对象指针
   注意:这个函数不会初始化expires,function,data这个三个字段,这三个字段需要程序员自己去指定,例如:
   init_timer(&mytimer);
   mytimer.expires = jiffies + 5*HZ
   mytimer.function = mytimer_funtion;
   mytimer.data = (unsigned long)&mydata;
3.向内核添加注册定时器
   add_timer(&mytimer); //一旦添加完毕,内核就开始对这个定时器进行倒计时!时钟中断处理函数每隔10ms检查一次定时器是否到期,如果到期,内核执行对应的定时器处理函数,并且将定时器进行删除。
4.删除定时器
   del_timer(&mytimer); //定时器到期,内核会帮你删除定时器,如果定时器没到期,可以使用此方法进行删除。
5.修改定时器的超时时间
   mod_timer(&mytimer, jiffies + 2*HZ); //设置定时器的超时时间为2秒以后
   相当于= del_timer 先将原先定时器删除 
   + expires = jiffies + 2*HZ  设置新的超时时间
   + add_timer  重新添加定时器
注意:千万不能用以上三步骤来实现mod_timer,以上三步骤的执行路径不是原子的,有可能被打断!

6.注意:定时器的实现基于软中断,所以定时器的处理函数同样不能进行休眠操作!

7.如果想让定时器的处理函数重复执行,循环执行,只需在定时器处理函数中重新添加定时器即可!

案例1:利用定时器,每隔2秒钟打印"hello ,tarena"
案例2:利用定时器,每个2秒开关灯;
案例3:利用模块参数的知识(不能采用字符设备驱动框架)来动态修改灯的闪烁频率;2000ms,1000ms,500ms,200ms.
注意:加载完驱动模块以后,无需卸载的情况下,动态修改闪烁的频率!提示:权限为0或者非0

实验步骤:
insmod mytimer_drv.ko speed = 2000 //2秒闪烁
echo 500 > /sys/module/mytimer_drv/parameters/speed //500ms

毫秒和jiffies转换:
unsigned long timeout = jiffies + msecs_to_jiffies(500);
unsigned long timeout = jiffies + HZ/2;

猜你喜欢

转载自blog.csdn.net/coolperl/article/details/81273895
今日推荐