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

2023-05-16

目录

一、睡眠函数种类

1、原子上下文

2、非原子上下文

    二、使用环境

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

2、驱动机制不同

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

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

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

2、输出结果

3、输出结果现象与解释


内核中的睡眠、延时函数

一、睡眠函数种类


1、原子上下文


使用delay系列函数

ndelay(unsigned long nsecs)//首选使用
udelay(unsigned long usecs)
mdelay(unsigned long msecs)


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

2、非原子上下文


使用sleep系列的函数

usleep_range(umin,umax);  //推荐使用
msleep(ms);
msleep_interruptible(ms);
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()函数的延时

#include <linux/ktime.h>
t1 = ktime_get_real_ns();
foo();
bar();
t2 = ktime_get_real_ns();
time_taken_ns = (t2 -> t1);

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

计算时间的函数

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

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

static int __init delays_and_sleeps_init(void)
{

        //delay        
        DILLY_DALLY("ndelay() for         10 ns", ndelay(10));
        DILLY_DALLY("udelay() for     10,000 ns", udelay(10));
        DILLY_DALLY("mdelay() for 10,000,000 ns", mdelay(10));

        
        //sleep
        DILLY_DALLY("usleep_range(10,20) for 10,000 ns", usleep_range(10, 20));
        DILLY_DALLY("msleep(10) for      10,000,000 ns", msleep(10));
        DILLY_DALLY("msleep_interruptible(10)         ", msleep_interruptible(10));
        DILLY_DALLY("ssleep(1)                        ", ssleep(1));

}

2、输出结果

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

3、输出结果现象与解释

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

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

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

原因有下

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


参考内核

内核说明文档


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux内核中的睡眠函数*delay、*sleep 的相关文章

随机推荐

  • K8s ❉ node节点未找到cni0/flannel.1网络

    问题描述 xff1a 现有测试环境有3台k8s服务器 xff0c 现在新添加两台服务器 xff0c 发现新加的服务器flannel 1和cni0网卡没有生成 root 64 slave1 ifconfig docker0 flags 61
  • 学习一下freertos streambuffer

    学习一下freertos stream buffer 最近在自己从0到1写rtos xff0c 主要是为了学习rtos xff0c 并没有其他卵用 xff0c 光学会调API是不够的 xff0c 看源码又恼火 xff0c 所以学习的最好办法
  • Writable接口

    在org apache hadoop io中 xff0c hadoop使用自己的序列化格式Writables接口 xff0c 具有紧凑 xff0c 快速的特点 xff0c 不过目前只有用Java才能较容易扩展 在hadoop中 xff0c
  • 解决数据库连接慢问题

    解决数据库连接慢问题方法 xff1a 方法一 连接数据库时 xff0c 使用localhost xff0c 不要使用明确的IP地址 xff08 远程数据库除外 xff09 xff1b 方法二 在my cnf配置文件里 xff0c 添加ski
  • 难忘的2011

    前言 xff1a 这些年 xff0c 每到年终之时 xff0c 我都会写个总结 2009年的 优化生活 规划未来 记录了一位初级网络优化工程师09年的所想与所做以及对10年的规划与展望 xff1b 2010年的 今天的2010 xff0c
  • QT从字体名获取字库文件路径(从宋体获取到simsun.ttc)

    MFC版本的从字体名获取字库文件路径点击此处 最近弄的一份项目需要裁剪ttf字库 xff0c 故需要用到此功能 xff01 用了几年QT xff0c 个人感觉类库是非常强大的 xff01 QT相比VS的话亮点在开源的类库非常的丰富 xff0
  • C++编写分形问题

    目的 xff1a 递归是基本的算法思想和设计方法之一 xff0c 也是数据结构重点讲授的部分 xff0c 是许多算法的基础 xff0c 对它们的理解和运用直接关系着其他算法的理解和应用 因此 xff0c 熟练掌握递归是十分重要的 通过本题
  • MFC从字体名获取字库文件路径(从宋体获取到simsun.ttc)

    上一篇有讲到在QT中从字体名获取文字的路径 xff0c 这个是MFC版本的 xff1a QT从字体名获取字库文件路径 include lt string gt using namespace std void wcharTochar con
  • 如何在 IntelliJ IDEA 中快速生成 JavaDoc 注释模板

    笔者的工作环境 xff1a IntelliJ IDEA 2021 2 2 Ultimate Edition JDK 17 使用 IntelliJ IDEA 中的实时模块可以快速生成 JavaDoc 注释 方法如下 xff1a xff08 I
  • FYI,PFA

    FYI For Your Information 供您参考 PFA please find attached 请参看附件
  • ArcGISEngine10.0安装后因为授权问…

    ArcGISEngine10 0 安装后因为授权问题无法使用 xff0c 添加控件提示错误 例如 xff1a 创建组件 ToolbarControl 失败 错误消息为 xff1a System ComponentModel LicenseE
  • 关于transition-group报错children must be keyed: div

    学习项目时遇到了这个报错 原来的写法 lt div v for 61 34 ball in balls 34 v show 61 34 ball show 34 class 61 34 ball 34 gt lt div class 61
  • 为什么老板对项目时间安排的永远是那么的紧?

    简单分析一下 xff0c 原因基本上也就这么两点 xff0c 一方面 xff0c 可以压缩你的时间 xff0c 大家都知道时间就是公司的最大成本 xff0c 用的时间越少 xff0c 带来的价格也就越高 1年完成的项目 半年提前完成 xff
  • GCC NOT FOUNT

    错误提示 xff1a arm linux gcc Command not found 原因 xff1a 1 xff09 没有在 bashrc 或者 etc environment中添加交叉编译工具链bin文件路径 解决方法 xff1a 使用
  • 记录个人编译DCNv2的过程(windows 10,vs2019, torch1.7.0)

    小白一个 xff0c 因为配FairMOT环境需要用到DCNv2 xff0c 就简单记录一下自己遇到的问题和解决方法 如有错误 xff0c 请多指教 首先主要参考了博客https blog csdn net Ningmoua article
  • 初识CMMI2.0

    初识 CMMI2 0 xff08 以下内容根据网络知识学习和整理而成 xff09 正式发布与获取 xff1a 2018 年 3 月 8 日 xff0c CMMI2 0 正式版本正式上线全新的主页 xff08 https cmmiinstit
  • C++编写杨辉三角

    xff08 1 xff09 美观很重要 xff0c 哈哈哈 include lt iostream gt include lt iomanip gt using namespace std int YangHuiData int n n是杨
  • IP地址的分类及范围详解:A、B、C、D、E五类是如何划分的

    IP地址类型 最初设计互联网络时 xff0c 为了便于寻址以及层次化构造网络 xff0c 每个IP地址包括两个标识码 ID xff0c 即网络ID和主机ID 同一个物理网络上的所有主机都使用同一个网络ID xff0c 网络上的一个主机 包括
  • iscsiadm命令基本用法

    发现目标 iscsiadm m discovery t sendtargets p 192 168 1 1 3260 m discovery 指定模式为discovery p 192 168 1 1 3260 指定目标ip和端口 登入节点
  • linux内核中的睡眠函数*delay、*sleep

    目录 一 睡眠函数种类 1 原子上下文 2 非原子上下文 二 使用环境 1 使用环境的不同 xff0c 选择不同的延时 2 驱动机制不同 3 内核中的计算函数执行的函数 三 实测两类函数的延时以及原因 1 测试系统中的睡眠函数 2 输出结果