当前位置:   article > 正文

linux内核中的睡眠函数*delay、*sleep_内核sleep

内核sleep

目录

一、睡眠函数种类

1、原子上下文

2、非原子上下文

    二、使用环境

1、使用环境的不同,选择不同的延时

2、驱动机制不同

3、内核中的计算函数执行的函数

三、实测两类函数的延时以及原因

1、测试系统中的睡眠函数

2、输出结果

3、输出结果现象与解释


内核中的睡眠、延时函数

一、睡眠函数种类


1、原子上下文


使用delay系列函数

  1. ndelay(unsigned long nsecs)//首选使用
  2. udelay(unsigned long usecs)
  3. mdelay(unsigned long msecs)


   这些函数使用对时钟速度的jiffie估计,并将忙于等待足够的循环周期以实现所需的延迟。
    mdelay是udelay的宏包装器,以免udelay传递大参数时可能发生溢出.
    

2、非原子上下文


使用sleep系列的函数

  1. usleep_range(umin,umax);  //推荐使用
  2. msleep(ms);
  3. msleep_interruptible(ms);
  4. ssleep(s);


    
二、使用环境

1、使用环境的不同,选择不同的延时

    -- Backed by busy-wait loop:
        udelay(unsigned long usecs)

    -- Backed by hrtimers:
        usleep_range(unsigned long min, unsigned long max)

    -- Backed by jiffies / legacy_timers
        msleep(unsigned long msecs)
        msleep_interruptible(unsigned long msecs)


2、驱动机制不同

1)睡眠时间 ( < ~10us? ):

        使用 udelay

为什么不使用 usleep?因为在较慢的系统上(如嵌入式)为usleep设置hrtimer的开销可能不值得。

2)睡眠时间 (10us - 20ms):
        使用usleep_range 
        为什么不使用msleep 定时 (1ms - 20ms), 

                睡眠时间经常比设定的长  http://lkml.org/lkml/2007/8/3/250
        为什么没有 "usleep",什么是好的范围?
               usleep建立在hrtimers计时器之上,唤醒将非常精确。因此,一个简单的usleep函数可能会引入大量不需要的中断。  随着范围的引入,调度器可以自由地将您的唤醒与可能由于其他原因发生的任何其他唤醒合并,或者在最坏的情况下,为您的上限触发一个中断。    
    
3)睡眠时间>10ms

        使用 msleep or msleep_interruptible

msleep 设置当前的进程状态为TASK_UNINTERRUPTIBLE
msleep_interruptible 设置当前的进程状态为TASK_INTERRUPTIBLE

4)睡眠时间>1s

        使用ssleep

3、内核中的计算函数执行的函数

u64 ktime_get_real_ns(void);

实例计算foo() bar()函数的延时

  1. #include <linux/ktime.h>
  2. t1 = ktime_get_real_ns();
  3. foo();
  4. bar();
  5. t2 = ktime_get_real_ns();
  6. time_taken_ns = (t2 -> t1);

三、实测两类函数的延时以及原因

计算时间的函数

  1. #define DILLY_DALLY(code_str, run_this) do { \
  2. u64 t1, t2; \
  3. t1 = ktime_get_real_ns(); \
  4. run_this; \
  5. t2 = ktime_get_real_ns(); \
  6. pr_info(code_str "-> actual: %11llu ns = %7llu us = %4llu ms\n", \
  7. (t2-t1), (t2-t1)/1000, (t2-t1)/1000000);\
  8. } while(0)

1、测试系统中的睡眠函数

  1. static int __init delays_and_sleeps_init(void)
  2. {
  3. //delay
  4. DILLY_DALLY("ndelay() for 10 ns", ndelay(10));
  5. DILLY_DALLY("udelay() for 10,000 ns", udelay(10));
  6. DILLY_DALLY("mdelay() for 10,000,000 ns", mdelay(10));
  7. //sleep
  8. DILLY_DALLY("usleep_range(10,20) for 10,000 ns", usleep_range(10, 20));
  9. DILLY_DALLY("msleep(10) for 10,000,000 ns", msleep(10));
  10. DILLY_DALLY("msleep_interruptible(10) ", msleep_interruptible(10));
  11. DILLY_DALLY("ssleep(1) ", ssleep(1));
  12. }

2、输出结果

  1. 1. *delay() functions (atomic, in a delay loop):
  2. [ 4176.946228] ndelay() for 10 ns-> actual: 219 ns = 0 us = 0 ms
  3. [ 4176.946239] udelay() for 10,000 ns-> actual: 9956 ns = 9 us = 0 ms
  4. [ 4176.956217] mdelay() for 10,000,000 ns-> actual: 9976582 ns = 9976 us = 9 ms
  5. [ 4176.956219]
  6. 2. *sleep() functions (process ctx, sleeps/schedule()'s out):
  7. [ 6372.868032] usleep_range(10,20) for 10,000 ns-> actual: 57183 ns = 57 us = 0 ms
  8. [ 6372.886923] msleep(10) for 10,000,000 ns-> actual: 18880096 ns = 18880 us = 18 ms
  9. [ 6372.906874] msleep_interruptible(10) -> actual: 19943338 ns = 19943 us = 19 ms
  10. [ 6373.915691] ssleep(1) -> actual: 1008605369 ns = 1008605 us = 1008 ms

3、输出结果现象与解释

1、udelay() 与mdelay() 函数实际用的时间比参数要少?这是为什么呢?

  1. * Please note that ndelay(), udelay() and mdelay() may return early for
  2. * several reasons:
  3. * 1. computed loops_per_jiffy too low (due to the time taken to
  4. * execute the timer interrupt.)
  5. * 2. cache behaviour affecting the time it takes to execute the
  6. * loop function.
  7. * 3. CPU clock rate changes.
  8. *

2、sleep()系列的函数用了更多的时间,在标准的linux上

原因有下

  • 标准的linux系统,高分辨率的定时器,它支持需要小于一个jiffy分辨率的计时器;
  • 将Linux操作系统配置为RTOS,将减少这个问题


参考内核

内核说明文档


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/224947
推荐阅读
相关标签
  

闽ICP备14008679号