驱动开发者怎么选择合适的延时方式呢?
首先,也是最重要的,你要搞明白“自己的代码是否是坐落原子上下文的?”,之后是否真的须要在一个原子上下文中延时?
对于原子上下文的情况,你必须使用‘*delay’相关的函数,这种函数使用时钟速率的jiffie预市值而且通过忙等待足够的循环次数实现指定的延时,这种函数如下:
<pre data-lang="text/x-csrc@clike@C" codecontent="ndelay(unsigned long nsecs)
udelay(unsigned long usecs)
mdelay(unsigned long msecs)" class=" language-clike">
udelay一般是首选的API;ndelay在个别非PC设备上可能会不精确;mdelay是基于udelay的宏扩充,用于处理传入udelay过大值而溢出的情况,一般不建议使用mdelay而是构建代码来使用msleep。(纳秒延时早已很长了,msleep容许休眠)
对于非原子上下文,可以使用‘*sleep[_range]’相关函数,对于同一个延时需求可能多个函数都能胜任,不过选择最合适的sleep函数有助于调度器的合理调度,可以优化帧率,也能让你的驱动更好。函数如下:
<pre data-lang="text/x-csrc@clike@C" codecontent="usleep_range(unsigned long min, unsigned long max)
msleep(unsigned long msecs)
msleep_interruptible(unsigned long msecs)" class=" language-clike">
usleep_range基于hrtimers(高精度时钟)实现,msleep基于jiffies或则传统计时器实现。这种函数的底层实现不同,使用时要注意。
对于大于10us的延时linux命令行,使用udelay即可,因为时间太紧linux内核延时函数,构造基于hrtimers的usleep在一些速率慢的系统上不实惠。其实这取决于你的应用场景linux内核延时函数,而且要注意到这点。
对于10us-20ms的延时,使用usleep_range,它指定了一个延时范围,最早会在min睡醒,最年会在max睡醒。对于1ms-20ms使用msleep经常延时过长(一般都是20ms),这其实不是我们所期望的结果。
为何没有usleep而是usleep_range?怎么选择合适的range?
因为usleep_range构建在hrtimers之上,唤起将十分精确(ish),因而一个简单的usleep函数可能会引入大量不须要的中断。
通过引入范围,调度程序可以自由地将您的唤起与可能因为其他诱因发生的任何其他唤起合并,或则在最坏的情况下linux伊甸园论坛,为您的上限触发中断。
你提供的范围越大,你不会触发中断的机会就越大;这应当与特定代码的延后/性能可接受的上限相平衡。此处的确切容差因情况而异,因而由调用者确定合理的范围。
假如延时10ms以上,可以使用msleep或则msleep_interruptible,后者设置当前任务状态为TASK_UNINTERRUPTIBLE,前者设置当前任务为TASK_INTERRUPTIBLE,可以通过讯号打断。通常使用msleep,除非你有明晰的打断延时需求才选择msleep_interruptible。
最后还提供了一个灵活的睡眠函数——fsleep(unsignedlongusecs),它可以延时任意宽度,并且不可中断。它底层实际上会依据不同的延时宽度调用上面的延时函数。