1.内核定时器
1.1 HZ和jiffies
系统定时器以可编程的频率中断处理器,此频率即为每秒的定时器节拍数,对应着内核变量HZ,HZ越大,定时器间隔越小,进程调用的准确性也会越高,但是HZ越大也会导致开销和电源消耗增大,更多的处理器周期耗费在定时器中断上下文中。
HZ的值取决于体系架构,通常为50-1200,定义在或者该文件包含的某个子平台相关的文件中。
jiffies变量记录了系统启动以来,系统定时器已经触发的次数,内核每秒钟将jiffies变量增加HZ次,因此,对应HZ为100的系统,一个jiffy等于10ms,对应HZ为1000的系统,一个jiffy对应1ms。
注意,jiffies变量定义为volatile,它告诉编译器不要优化该变量的存取,确保每次都会从内存去拿该数据,保证了该变量的最新状态。
下面的代码摘自drivers/ide/ide.c,使用到了jiffies和HZ
- unsigned int timeout = jiffies + (3*HZ); //timeout after 3s.
- while(hwgroup->busy){
- /*...*/
- if(time_after(jiffies,timeout)) // return -EBUSY after 3s if hwgroup is always busy.
- return -EBUSY;
- /*...*/
- }
1.2 长延时
在内核中,以jiffies为单位的延时都认为是长延时。长延时技术仅仅适用于进程上下文,因为睡眠等待不能用于中断上下文。
几种长延时技术:
①. 忙等待:站着茅坑不拉屎,可能的代码片段如下:
- unsigned int timeout = jiffies + HZ;
- while(time_before(jiffies,timeout))
- continue;
②. 睡眠等待:在等待过程中让出处理器,可能的代码片段如下:
- unsigned int timeout = HZ;
- schedule_timeout(timeout);
//另外两个用于睡眠等待的函数:
wait_event_timeout(); //在一个特定条件满足或者超时发生后,希望代码继续运行。
msleep(); // ms as unit
③. 内核定时器API
- #include<linux/timer.h>
- struct timer_list my_timer;
- init_timer(&my_timer);
- my_timer.expire = jiffies + n * HZ;
- my_timer.function = timer_func;
- my_timer.data = func_parameter;
- add_timer(&my_timer);
- //上述代码只会让定时器运行一次,如果要周期性运行,需在timer_func中重新初始化一次
- static void timer_func(unsigned long func_parameter)
- {
- /*...*/
- init_timer(&my_timer);
- my_timer.expire = jiffies + n * HZ;
- my_timer.function = timer_func;
- my_timer.data = func_parameter;
- add_timer(&my_timer);
- }
另外还有mod_timer修改定时器expire时间,del_timer()取消定时器,或者用timer_pending()查看my_timer是否处于等待状态。查看kernel/timer.c发现schedule_timeout()内部使用了这些API.
1.3 短延时
在内核中,小于jiffies的延时认为是短延时,在进程上下文或者中断上下文都有可能发生,此时唯一的解决办法就是使用忙等待。
实现短延时的API包括:
#include
void mdelay(unsigned long);
- void udelay(unsigned long);
- void ndelay(unsigned long);
这三个函数分别对应ms,us,ns级的短延时,具体实现取决于体系架构。
忙等待的实现方法是测量处理器执行一条指令的时间,为了延时,执行一定数量的指令。
2.延缓操作
中断处理程序要求尽可能的快,但是如果我们需要在响应中断处理中完成大量的设备数据处理,此时就产生了一个矛盾,因此中断处理过程被分成两部分:一个急切抢占并与硬件交互的顶半部,一个处理所有使能的中断的并不急切的底半部。如下三种机制可以将工作解析到底半部执行:
* softirq
* tasklet
* work queue
下图对三种机制进行了对比:
阅读(300) | 评论(0) | 转发(0) |