内核中涉及的延时主要有两种实现方式:忙等待或者睡眠等待。前者阻塞程序,在延时时间到达前一直占用CPU,而后者是将进程挂起(置进程于睡眠状态并释放CPU资源)。所以,前者一般用在延时时间在毫秒以内的精确延时,后者用于延时时间在毫秒以上的长延时。为了充分利用 CPU 资源,使系统有更好的吞吐性能,在对延迟时间的要求并不是很精确的情况下,睡眠等待通常是值得推荐的。

1、忙等待短延时

内核中提供了如下3个函数用于纳秒、微秒和毫秒级的延时:

void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs); //一般不建议直接使用mdelay()函数,这将无谓地耗费 CPU 资源

上述延迟的实现原理本质上是忙等待,它根据 CPU 频率进行一定次数的循环。其本质同如下代码:

void delay(unsigned int time)
{ while (time--);
}

2、忙等待长延时函数

内核中进行延迟的一个很直观的方法是比较当前的 jiffies 和目标 jiffies(设置为当前 jiffies 加上时间间隔的 jiffies),直到未来的 jiffies 达到目标 jiffies。

  • 利用jiffies和time_befor实现延时100个jiffies和2秒的代码:
 /*延迟 100 个 jiffies*/ unsigned long delay = jiffies + 100; while (time_before(jiffies, delay)); /*再延迟 2s*/ unsigned long delay = jiffies + 2*HZ; while (time_before(jiffies, delay));

其中,time_befor()只是一个函数宏,与其对应的还有一个time_after():

#define time_after(a,b) \ (typecheck(unsigned long, a) && \ typecheck(unsigned long, b) && \ ((long)(b) - (long)(a) < 0)) #define time_before(a,b) time_after(b,a)

3、睡眠短延时

3.1 sleep类延时函数

下述函数将使得调用它的进程睡眠参数指定的时间,受系统 HZ 和进程调度的影响,msleep()类似函数的精度是有限的。msleep()、ssleep()不能被打断,而msleep_interruptible()则可以被打断。

void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
void ssleep(unsigned int seconds);

3.2 schedule类睡眠延时函数

signed long  schedule_timeout_interruptible(signed long timeout);signed long  schedule_timeout_uninterruptible(signed long timeout)

schedule_timeout()可以使当前任务睡眠指定的jiffies 之后重新被调度执行,它的实现原理是向系统添加一个定时器,在定时器处理函数中唤醒参数对应的进程。上一小节的sleep类函数的底层实现也是调用它实现的:

void msleep(unsigned int msecs)
{ unsigned long timeout = msecs_to_jiffies(msecs) + 1; while (timeout) timeout = schedule_timeout_uninterruptible(timeout);
} unsigned long msleep_interruptible(unsigned int msecs)
{ unsigned long timeout = msecs_to_jiffies(msecs) + 1; while (timeout && !signal_pending(current)) timeout = schedule_timeout_interruptible(timeout); return jiffies_to_msecs(timeout); //返回剩余的延时时间
}signed long _ _sched schedule_timeout_interruptible(signed long timeout)
{ _ _set_current_state(TASK_INTERRUPTIBLE); //置进程状态为 TASK_INTERRUPTIBLEreturn schedule_timeout(timeout);
} signed long _ _sched schedule_timeout_uninterruptible(signed long timeout)
{ _ _set_current_state(TASK_UNINTERRUPTIBLE); //置进程状态为 TASK_UNINTERRUPTIBLEreturn schedule_timeout(timeout);
}

3.3 sleep_on类,在等待队列上睡眠的延时函数

函数可以将当前进程添加到等待队列中,从而在等待队列上睡眠。当超时发生时,进程将被唤醒(后者可以在超时前被打断):

sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout); interruptible_sleep_on_timeout(wait_queue_head_t*q, unsigned long timeout);

Linux内核中的延时函数详解相关推荐

  1. linux内核中的hook函数详解,linux内核中的hook函数详解

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

  2. linux hook 任意内核函数,linux内核中的hook函数详解

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

  3. Linux 内核中RAID5源码详解之守护进程raid5d

    Linux 内核中RAID5源码详解之守护进程raid5d 对于一个人,大脑支配着他的一举一动:对于一支部队,指挥中心控制着它的所有活动:同样,对于内核中的RAID5,也需要一个像大脑一样的东西来支配 ...

  4. 内核中的kmalloc函数详解

    一.kmalloc函数详解 #include <linux/slab.h> void *kmalloc(size_t size, int flags); 给 kmalloc 的第一个参数是 ...

  5. linux内核kconfig objs,linux内核中Kconfig和Makefile 详解

    内核源码树的目录下都有两个文档 Kconfig (2.4版本是Config.in)和Makefile.分布到各目录的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录 ...

  6. linux64位ioremap函数,linux操作系统中的ioremap函数详解

    在编写驱动程序的过程中,我们总免不了要使用ioremap函数来将我们的硬件的地址映射到系统的虚拟地址空间. ioramp函数原型: #define ioremap(cookie,size) __ior ...

  7. 【Linux系统编程】fork()函数详解

    00. 目录 文章目录 00. 目录 01. 进程创建函数 02. 父子进程结构 03. 父子进程地址空间 04. 附录 01. 进程创建函数 #include <sys/types.h> ...

  8. 【Linux系统编程】vfork() 函数详解

    00. 目录 文章目录 00. 目录 01. vfork函数 02. fork和vfork区别 03. 父子进程地址空间 04. 附录 01. vfork函数 函数分析 #include <sy ...

  9. linux系统里route -n不起作用,Linux系统中traceroute命令使用详解

    Linux系统中traceroute命令可以追踪到网络数据包的路由途径.下面由学习啦小编为大家整理了linux系统中traceroute命令使用详解,希望对大家有帮助! Linux系统中tracero ...

最新文章

  1. java keytool 代码_JDK keytool证书工具功能代码解析_java_脚本之家
  2. 成功解决mxnet-tag\mxnet\src\operator\tensor\./matrix_op-inl.h:189: Using target_shape will be deprecated
  3. 关于centos6升级python3.6无法使用pip的问题
  4. .NET CORE(C#) WPF简单菜单MVVM绑定
  5. datavideo切换台说明书_【新品发布】datavideo SE-650 高清四通道切换台
  6. linux分割图片软件,桌面应用|5 种拆分 Linux 终端的方法
  7. 用一个参数化的模型来投影点
  8. 这个大部分CNS都会用到的技术分析流程大放送......
  9. 买mac电脑的各个使用阶段:
  10. PetShop之业务逻辑层设计
  11. 反射机制在JDBC连接中的使用
  12. 【转】网络安全-------防止被抓包
  13. 批标准化 tf.keras.layers.BatchNormalization 参数解析与应用分析
  14. java 生成Excel开门篇
  15. win2008 时间同步命令
  16. 增值税发票识别,智能自动识别
  17. 面向对象的系统分析(一)-系统分析方法
  18. 幻14 连不上无线网 网卡掉驱动
  19. 5G NTN进展简述
  20. 用户网络接口UNI和网络节点接口NNI

热门文章

  1. 最新安卓官方api文档完整版
  2. 好玩的读心术猜数字游戏
  3. pyhton interpreter byterun和底层`code object`的简单了解
  4. 图形处理(八)点云重建(上)点云滤波、尖锐特征边增采样、移除离群点
  5. 如何在A4相纸上打印4张5寸相片
  6. win10设置文件默认打开方式
  7. php直接读取csv文件,php怎么读取csv文件?
  8. 深入理解Spring IoC的原理(转发)
  9. 【Java网络编程】:JDK API实现OIO和NIO
  10. 黑客学习-SQL注入:利用Havij对PHPCMS网站进行SQL注入