歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux Kernel中如何使用高精度timer(hrtimer)

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

日期:2017/2/28 15:55:13   编辑:Linux教程

前面已經講過,高精度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. if (timeout > 0) {
  10. struct timespec end_time = ep_set_mstimeout(timeout);
  11. slack = select_estimate_accuracy(&end_time);
  12. to = &expires;
  13. *to = timespec_to_ktime(end_time);
  14. } else if (timeout == 0) {
  15. /*
  16. * Avoid the unnecessary trip to the wait queue loop, if the
  17. * caller specified a non blocking operation.
  18. */
  19. timed_out = 1;
  20. spin_lock_irqsave(&ep->lock, flags);
  21. goto check_events;
  22. }
  23. fetch_events:
  24. spin_lock_irqsave(&ep->lock, flags);
  25. if (!ep_events_available(ep)) {
  26. /*
  27. * We don't have any available event to return to the caller.
  28. * We need to sleep here, and we will be wake up by
  29. * ep_poll_callback() when events will become available.
  30. */
  31. init_waitqueue_entry(&wait, current);
  32. __add_wait_queue_exclusive(&ep->wq, &wait);
  33. for (;;) {
  34. /*
  35. * We don't want to sleep if the ep_poll_callback() sends us
  36. * a wakeup in between. That's why we set the task state
  37. * to TASK_INTERRUPTIBLE before doing the checks.
  38. */
  39. set_current_state(TASK_INTERRUPTIBLE);
  40. if (ep_events_available(ep) || timed_out)
  41. break;
  42. if (signal_pending(current)) {
  43. res = -EINTR;
  44. break;
  45. }
  46. spin_unlock_irqrestore(&ep->lock, flags);
  47. if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
  48. timed_out = 1;
  49. spin_lock_irqsave(&ep->lock, flags);
  50. }
  51. __remove_wait_queue(&ep->wq, &wait);
  52. set_current_state(TASK_RUNNING);
  53. }
  54. check_events:
  55. /* Is it worth to try to dig for events ? */
  56. eavail = ep_events_available(ep);
  57. spin_unlock_irqrestore(&ep->lock, flags);
  58. /*
  59. * Try to transfer events to user space. In case we get 0 events and
  60. * there's still timeout left over, we go trying again in search of
  61. * more luck.
  62. */
  63. if (!res && eavail &&
  64. !(res = ep_send_events(ep, events, maxevents)) && !timed_out)
  65. goto fetch_events;
  66. return res;
  67. }
Copyright © Linux教程網 All Rights Reserved