内核延时
查阅内核代码时经常看到和应用到延时,本文用于归纳延时相关内容。
一. 短延时
void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsigned long msecs);
短延时的本质是忙等。
毫秒时延已经很大了,在内核中,最好不要直接使用mdelay(),无谓消耗cpu资源,对于毫秒级以上时延,内核提供如下函数:
void msleep(unsigned int msecs); unsigned long msleep_interruptible(unsigned int msecs); void ssleep(unsigned long secs);
msleep(),ssleep()不能被打断,msleep_interruptible()则可以被打断。
二. 长延时
内核中进行延时的一个很直观的方法是比较当前的jiffies和目标jiffies,直到未来的jiffies达到目标jiffies。
unsigned long delay = jiffies + 100; while(time_before(jiffies, delay)); unsigned long delay = jiffies + 2*Hz; while(time_before(jiffies, delay));
延时100jiffies,然后再延时2s。
#define time_after(a,b) \ (typecheck(unsigned long, a) && \ typecheck(unsigned long, b) && \ ((long)((b) - (a)) < 0)) #define time_before(a,b) time_after(b,a)
不推荐(禁止)直接jiffies值比较,因为jiffies有溢出,必须考虑wrap,推荐使用time_after()和time_before()。
三. 睡眠延时
linux/sched.h extern signed long schedule_timeout(signed long timeout); extern signed long schedule_timeout_interruptible(signed long timeout); extern signed long schedule_timeout_killable(signed long timeout); extern signed long schedule_timeout_uninterruptible(signed long timeout);
schedule_timeout()可以使当前任务睡眠指定的jiffies之后重新调度执行,msleep()和msleep_interruptible()本质就是依靠schedule_timeout_uninterruptible()和schedule_timeout_interruptible()实现的。
extern void sleep_on(wait_queue_head_t *q); extern long sleep_on_timeout(wait_queue_head_t *q, signed long timeout); extern void interruptible_sleep_on(wait_queue_head_t *q); extern long interruptible_sleep_on_timeout(wait_queue_head_t *q, signed long timeout);
将当前进程添加到等待队列中,从而在等待队列上睡眠。当超时发生时,进程被唤醒。
参考:
1. 设备驱动开发详解 宋宝华
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· ShadowSql之.net sql拼写神器
· 使用MCP C# SDK开发MCP Server + Client
· 感觉程序员要被 AI 淘汰了?学什么才有机会?
· MQTT协议发布和订阅的实现,一步步带你实现发布订阅服务。
2017-03-18 inode表元数据,存储在物理存储体上
2016-03-18 git常用操作
2016-03-18 linux内核学习
2016-03-18 截图工具gsnap