我是靠谱客的博主 大气大山,最近开发中收集的这篇文章主要介绍linux kernel --- 延迟函数udelay msleep usleep_range...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

linux 驱动开发过程中,经常会用到延迟函数:udelay,mdelay,usleep,msleep,usleep_range…

一、mdelay和msleep的本质区别

1、从模块本身分析:

mdelay,属于忙等待函数(相当于for循环),在延迟过程中无法运行其他任务,这个时间是准确的,需要等待多少实际就会等待多少时间;
msleep,属于休眠函数,不会忙等待,时间是不准确的,比如msleep(200),大概率是会等待多于200ms的。

2、从系统角度分析:

mdelay,会占用系统资源,导致其他功能此时也无法使用cpu;
msleep,不会占用cpu资源,当该模块msleep时,其他模块可以占用cpu。sleep函数会让调用的进程进行休眠。

二、udelay,mdelay,ndelay 区别

时间单位不同
udelay:us
mdelay:ms
ndelay:ns
1s = 10^3ms = 10^6us = 10^9ns

三、What is the RightWay to insert a delay?

表面问题:在kernel4.14的code中使用udelay(500)时,报出了一个CHECIK:usleep_range is preferred over udelay;see Documentation/timers/timers-howto.txt
深层问题:What is the RightWay to insert a delay?
下面就参考Documentation/timers/timers-howto.txt 这篇文章,得出结论

1、首先:code是否在atomic context?

(1)atomic context

必须使用delay这一系列的函数。
udelay是通常首选的API。ndelay级别的精度实际上可能在许多非PC设备上并不存在。mdelay是udelay的衍生,当大参数传递给udelay时,可能产生溢出,这里就要使用mdelay。一般来说,不鼓励使用mdelay,应该重构代码以允许使用msleep。

(2)non-atomic context

使用sleep这一系列的函数。
这里有很多的选择,尽管其中任何一个都可能正常工作,使用“正确的”睡眠功能将有助于调度程序、电源管理,并使驱动程序更好。

2、底层实现由什么支持

(1) 由 busy-wait loop 支持:
udelay(unsigned long usecs)
(2) 由 hrtimers(高分辨率kernel定时器) 支持:
usleep_range(unsigned long min, unsigned long max)
(3) 由 jiffies / legacy_timers 支持:
msleep(unsigned long msecs) / msleep_interruptible(unsigned long msecs)

3、这些函数的一些怪癖

(1)sleeping for a few usecs(<10us左右)

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

(2)sleeping for usecs or small msecs(10us ~ 20ms左右)

使用usleep_range
为什么不用msleep for(1ms ~ 20ms)? msleep(1~20)可能无法实现调用者想要的效果,并且通常会睡得更长(对于1~20ms范围内给定的任何值,实际睡眠时间为~20ms)。在许多情况下,这不是期望的行为。
为什么没有“usleep”/什么是好的范围
由于usleep_range是建立在hrtimers之上的,唤醒将非常精确(ish),因此一个简单的usleep函数可能会引入大量不需要的中断。
通过引入一个范围,调度程序可以自由地将您的唤醒与可能由于其他原因而发生的任何其他唤醒合并起来,或者在最坏的情况下,为您的上限触发一个中断。
提供的范围越大,就越有可能不触发中断;这应该与特定代码路径的延迟/性能的可接受上限相平衡。这里的精确公差是根据具体情况而定的,因此由调用者来确定一个合理的范围。

(3)sleeping for larger msecs (>10ms左右)

使用msleep或者msleep_interruptible
这两者的区别?msleep将当前任务设置为TASK_UNINTERRUPTIBLE,而msleep_interruptible在安排睡眠之前将当前任务设置为TASK_INTERRUPTIBLE。简言之,区别在于sleep是否可以通过信号提前结束。一般来说,除非您知道您需要中断,否则只需使用msleep。

四、参考

(1) linux驱动开发延迟函数:msleep、mdelay、udelay介绍:
https://blog.csdn.net/qq_37858386/article/details/79716304
(2) Documentation/timers/timers-howto.txt

最后

以上就是大气大山为你收集整理的linux kernel --- 延迟函数udelay msleep usleep_range...的全部内容,希望文章能够帮你解决linux kernel --- 延迟函数udelay msleep usleep_range...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部