感谢支持
我们一直在努力

Linux Kernel中如何使用高精度timer(hrtimer)

前面已经讲过,高精度timer是通过hrtimer来实现的(见 http://www.linuxidc.com/Linux/2012-03/55892.htm ),hrtimer通过可编程定时器来现,在等待时,不占用CPU。


在用户态,只要我们调用usleep,则线程在kernel态执行时,则使用hrtimer进行不占CPU的等待。


在Kernel中如何使用的呢?


先看看eventpoll.c中的ep_poll函数:



  1. static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,  

  2.            int maxevents, long timeout)  

  3. {  

  4.     int res = 0, eavail, timed_out = 0;  

  5.     unsigned long flags;  

  6.     long slack = 0;  

  7.     wait_queue_t wait;  

  8.     ktime_t expires, *to = NULL;  

  9.   

  10.     if (timeout > 0) {  

  11.         struct timespec end_time = ep_set_mstimeout(timeout);  

  12.   

  13.         slack = select_estimate_accuracy(&end_time);  

  14.         to = &expires;  

  15.         *to = timespec_to_ktime(end_time);  

  16.     } else if (timeout == 0) {  

  17.         /* 

  18.          * Avoid the unnecessary trip to the wait queue loop, if the 

  19.          * caller specified a non blocking operation. 

  20.          */  

  21.         timed_out = 1;  

  22.         spin_lock_irqsave(&ep->lock, flags);  

  23.         goto check_events;  

  24.     }  

  25.   

  26. fetch_events:  

  27.     spin_lock_irqsave(&ep->lock, flags);  

  28.   

  29.     if (!ep_events_available(ep)) {  

  30.         /* 

  31.          * We don’t have any available event to return to the caller. 

  32.          * We need to sleep here, and we will be wake up by 

  33.          * ep_poll_callback() when events will become available. 

  34.          */  

  35.         init_waitqueue_entry(&wait, current);  

  36.         __add_wait_queue_exclusive(&ep->wq, &wait);  

  37.   

  38.         for (;;) {  

  39.             /* 

  40.              * We don’t want to sleep if the ep_poll_callback() sends us 

  41.              * a wakeup in between. That’s why we set the task state 

  42.              * to TASK_INTERRUPTIBLE before doing the checks. 

  43.              */  

  44.             set_current_state(TASK_INTERRUPTIBLE);  

  45.             if (ep_events_available(ep) || timed_out)  

  46.                 break;  

  47.             if (signal_pending(current)) {  

  48.                 res = -EINTR;  

  49.                 break;  

  50.             }  

  51.   

  52.             spin_unlock_irqrestore(&ep->lock, flags);  

  53.             if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))  

  54.                 timed_out = 1;  

  55.   

  56.             spin_lock_irqsave(&ep->lock, flags);  

  57.         }  

  58.         __remove_wait_queue(&ep->wq, &wait);  

  59.   

  60.         set_current_state(TASK_RUNNING);  

  61.     }  

  62. check_events:  

  63.     /* Is it worth to try to dig for events ? */  

  64.     eavail = ep_events_available(ep);  

  65.   

  66.     spin_unlock_irqrestore(&ep->lock, flags);  

  67.   

  68.     /* 

  69.      * Try to transfer events to user space. In case we get 0 events and 

  70.      * there’s still timeout left over, we go trying again in search of 

  71.      * more luck. 

  72.      */  

  73.     if (!res && eavail &&  

  74.         !(res = ep_send_events(ep, events, maxevents)) && !timed_out)  

  75.         goto fetch_events;  

  76.   

  77.     return res;  

  78. }  
看到上面的schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)了吗?它就是hrtimer中调用来执行等待超时的函数

,其函数原型为:


/**
 * schedule_hrtimeout_range – sleep until timeout
 * @expires: timeout value (ktime_t)
 * @delta: slack in expires timeout (ktime_t)
 * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
 */
int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
         const enum hrtimer_mode mode)
{
 return schedule_hrtimeout_range_clock(expires, delta, mode,
           CLOCK_MONOTONIC);
}
      在ep_poll中,其slack和to的计算方法如下:


struct timespec end_time = ep_set_mstimeout(timeout);
slack = select_estimate_accuracy(&end_time);
to = &expires;
*to = timespec_to_ktime(end_time);


      如果你在Kernel中需要高精度timer,可以参照此方法实现自己的高精度timer超时。

赞(0) 打赏
转载请注明出处:服务器评测 » Linux Kernel中如何使用高精度timer(hrtimer)
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏