设备驱动常常需要延后一段时间执行一个特定片段的代码,常常允许硬件完成某个任务;
一个驱动需要延后执行相对长时间,
1,忙等待(慎用)
如果想延时执行多个时钟嘀嗒,允许在值中某些疏忽,最容易的实现是一个监视jiffy计数器的循环,
j1是延时超时的值
while(time_before(jiffies,j1))
cpu_relax();//
这个循环完全锁住处理器,计算机看起来完全死掉直到时间j1到;更严重的是,当进入循环时,如果中断碰巧被禁止,jiffies将不会被更新,并且while条件永远保持为真,那就完全卡死了
cpu_relax():不让cpu做任何事情;
2,让出处理器
可以通过调用调度函数来让出处理器,在<linux/sched.h>
while(time_before(jiffies,j1)){
schedule();
}
还是不够优化,当前进程除了释放CPU不作任何事情,但是它保留在运行队列中,如果它是唯一的可运行的进程,实际上它运行,
3,超时
有2个方法来建立一个基于jiffy的超时,依赖于是否你的驱动在等待其他的事件;
#include<linux/wait.h>
long wait_event_timeout(wait_queue_head_t q,condition, long timeout);
long wait_event_interruptible_timeout(wait_queue_head_t q,condition,long timeout);
这些函数在给定队列上睡眠,但是它们在超时(以jiffies表示)到后返回,因此,它们实现一个限定的睡眠不会一直睡下去,注意超时值表示要等待的jiffies数,不是一个绝对时间值,这个值由一个有符号数表示;
短延时
#include<linux/delay.h>
void ndelay(unsigned long nsecs); //纳秒
void udelay(unsigned long usecs);//微秒
void mdelay(unsigned long msecs);//毫秒
这些函数对于短延时好用,这三个函数是忙等待;
另一个方法可以获得毫秒甚至更长而不用涉及忙等待:
#include<linux/delay.h>
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
void ssleep(unsigned int seconds);
前2个函数使调用进程进入睡眠给定的毫秒数,一个对msleep的调用是不可中断的;
你能确保进程睡眠至少给定的毫秒数;
如果你的驱动位于一个等待队列并且你想唤醒来打断睡眠,使用msleep_interruptible,
从msleep_interruptible的返回值正常是0,但如果这个进程被提早唤醒,返回值是在初始请求睡眠周期中剩余的毫秒数;
对ssleep的调用使进程进入一个不可中断的睡眠给定的秒数;
内核定时器
无论何时你需要调度一个动作以后发生,而不阻塞当前进程直到时间到达,
内核定时器是一个工具,可以用来调度一个函数在将来的某个特定时间执行,基于时钟嘀嗒,并且可用作各类任务;
一个内核定时器是一个数据结构,它指导内核执行一个用户定义的函数使用一个用户定义的参数在一个用户定义的时间