如何在Linux内核空间中睡觉?

时间:2016-10-05 14:17:56

标签: linux linux-kernel thread-sleep

我有一个内核线程,它在具有FIFO和最高优先级的特定CPU上分配。该线程不时休眠,但时间间隔必须尽可能精确。那么考虑到这一点,在内核空间中最精确的睡眠方式是什么?

2 个答案:

答案 0 :(得分:13)

以下是Documentation/timers/timers-howto.txt的相关摘录:

  

非原子上下文:

     

您应该使用*sleep[_range]系列函数。     这里还有一些选择,而其中任何一个都可以     正确地工作,使用"权利"睡眠功能会     帮助调度程序,电源管理,并让你的     司机更好:)

     
      
  • 由忙等待循环支持:
        udelay(unsigned long usecs)
  •   
  • 由hrtimers支持:
        usleep_range(unsigned long min, unsigned long max)
  •   
  • 由jiffies / legacy_timers支持     msleep(unsigned long msecs)
        msleep_interruptible(unsigned long msecs)
  •   
     

*delay家族不同,是潜在的机制   驾驶这些呼叫各不相同,因此有   你应该知道的怪癖。

     

睡觉"很少" USECS(< ~10us?)

     
      
  • 使用udelay
         
        
    • 为什么不usleep
          在较慢的系统上,(嵌入式,或者可能是速度级的     PC!)设置hrtimers的开销     对于usleep 可能不值得。这样的评价     显然取决于你的具体情况,但是     这是值得注意的事情。
    •   
  •   
     

为USECS或小型MSEC(10us - 20ms)睡眠:

     
      
  • 使用usleep_range
         
        
    • 为什么msleep为(1ms - 20ms)?     原来在这里解释:
              http://lkml.org/lkml/2007/8/3/250
          msleep(1~20)可能无法执行调用者的意图,并且     经常睡得更久(实际睡眠时间约为20毫秒)     值在1~20ms范围内给出)。在很多情况下这个     不是理想的行为。
    •   
    • 为什么没有usleep /什么是好范围?
          由于usleep_range建立在hrtimers之上,因此     唤醒会非常精确(ish),因此很简单     usleep函数可能会引入大量函数     不希望的中断。
        
          随着范围的引入,调度程序就是     任何其他唤醒都可以自由地结合你的唤醒     这可能是出于其他原因,或在     最坏的情况,为你的上限发出一个中断   
          您提供的范围越大,机会就越大     你不会触发中断;这应该     与可接受的上限相平衡     特定代码路径的延迟/性能。精确     这里的公差是非常具体的情况,因此它     留给调用者以确定合理的范围。
    •   
  •   
     

为较大的MSECS(10ms +)睡眠

     
      
  • 使用msleep或可能msleep_interruptible      
        
    • 有什么区别?
          msleep将当前任务设置为TASK_UNINTERRUPTIBLE     而msleep_interruptible将当前任务设置为     在安排睡眠之前TASK_INTERRUPTIBLE。在     简而言之,区别在于睡眠是否可以结束     早期的一个信号。一般情况下,除非使用msleep     你知道你需要可中断的变种。
    •   
  •   

答案 1 :(得分:0)

我使用了hrtimer和waitqueue的组合来使用内核线程实现定期任务:

  1. 创建waitqueue和periodic hrtimer
  2. 使用wait_event()/wait_event_timeout()
  3. 阻止waitqueue上的内核线程
  4. 在hrtimer回拨电话wake_up()/wake_up_all()
  5. 另外,刚刚找到,您可以使用hrtimer_init_sleeper()schedule()实现睡眠,请参阅__wait_event_hrtimeout()do_nanosleep()。但是我在那里试过了。