Linux驱动之定时器和延时

转载地址:http://blog.csdn.net/king523103/article/details/43450345

内核中有一个时钟,时钟每次的tick都会触发一个时钟中断,中断时将检查是否有定时器到期,根据需要在软件中断中执行定时器函数。因此:

内核定时器在时钟中断的下半段执行,非进程的上下文

不能使用休眠函数

不能访问用户空间

更详细的执行过程:

参考:http://www.cnblogs.com/leaven/archive/2010/08/19/1803382.html

实际上,内核为定时器维护着两个全局变量jiffies和timer_jiffies。

jiffies表示当前的时钟,timer_jiffies表示上次中断发生的时钟。一般来说,每个时钟都会发生中断。

jiffies-timer_jiffies表示,距离上次中断这段时间里发生中断的数目。当这个值为3时,需要调用timer_list列表中序号为1,2,3的定时器。


每个定时器的使用下面数据结构描述。

  1. struct timer_list {  
  2.     struct list_head entry;  
  3.     unsigned long expires;  
  4.   
  5.     void (*function)(unsigned long);  
  6.     unsigned long data;  
  7.   
  8.     struct tvec_base *base;  
  9. #ifdef CONFIG_TIMER_STATS  
  10.     void *start_site;  
  11.     char start_comm[16];  
  12.     int start_pid;  
  13. #endif  
  14. #ifdef CONFIG_LOCKDEP  
  15.     struct lockdep_map lockdep_map;  
  16. #endif  
  17. };  

要使用定时器,首先得对定时器初始化:
  1. 方法一:  
  2. DEFINE_TIMER(timer_name, function_name, expires_value, data);  
  3. 方法二:  
  4. struct timer_list mytimer;  
  5. setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);  
  6. mytimer.expires = jiffies + 5*HZ;  

将定时器注册
  1. void add_timer(struct timer_list *timer)  
  2. {  
  3.     BUG_ON(timer_pending(timer));  
  4.     mod_timer(timer, timer->expires);  
  5. }  

使用完成后,将定时器进行注销
  1. int del_timer(struct timer_list *timer)  
  2. {  
  3.     struct tvec_base *base;  
  4.     unsigned long flags;  
  5.     int ret = 0;  
  6.   
  7.     timer_stats_timer_clear_start_info(timer);  
  8.     if (timer_pending(timer)) {  
  9.         base = lock_timer_base(timer, &flags);  
  10.         if (timer_pending(timer)) {  
  11.             detach_timer(timer, 1);  
  12.             ret = 1;  
  13.         }  
  14.         spin_unlock_irqrestore(&base->lock, flags);  
  15.     }  
  16.   
  17.     return ret;  
  18. }  

内核中维护着一个timer_list列表,注册和销毁的过程实际上就是添加或者删除列表的过程。

可以简单的认为这个列表中存在256个数组,内核在每个tick检查其中一个数组项,执行其中的定时器回调函数。

参考:http://blog.csdn.net/lizhiguo0532/article/details/6406161



和定时器相关的延时函数:

这些延时会浪费CPU资源:

mdelay  udelay  ndelay 以及time_before、time_after(高精度)

另外一种是让出CPU一段时间

  1. void msleep(unsigned int msecs)  
  2. {  
  3.     unsigned long timeout = msecs_to_jiffies(msecs) + 1;  
  4.   
  5.     while (timeout)  
  6.         timeout = schedule_timeout_uninterruptible(timeout);  
  7. }  
  1. unsigned long msleep_interruptible(unsigned int msecs)  
  2. {  
  3.     unsigned long timeout = msecs_to_jiffies(msecs) + 1;  
  4.   
  5.     while (timeout && !signal_pending(current))  
  6.         timeout = schedule_timeout_interruptible(timeout);  
  7.     return jiffies_to_msecs(timeout);  
  8. }  
从中可以看到,schedule_timeout和schedule_timeout_xxx实际上实现了sleep相关函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值