一、HZ、jiffies
HZ值是一个与体系结构有关的常数。其值表示每秒有多少次时钟中断。
每次当时钟中断发生时,内核内部计数器的值就增加1,这个计数器的值在系统引导时被初始化为0,因此,它的值就是自上次操作系统引导以来的时钟滴答数,这个计数器是一个64位的变量(即使在32位架构上也是64位),称为“jiffies_64”,但是驱动程序开发者通常访问的是jiffies变量,它是unsigned long型变量,要么和jiffies_64相同,要么仅仅是jiffies_64的低32位,通常首选使用jiffies,因为它的访问很快,从而对64位jiffies_64值的访问并不需要在所有架构上都是原子的。jiffies和jiffies_64均应被看作只读变量。
二、短延迟
如果a(jiffies的某个快照)所代表的时间比b靠后,则第一个宏返回真;如果a比b靠前,则第二个宏返回真;后面两个宏分别用来比较“靠后或者相等”及“靠前或者相等”。
用等待队列实现延时:
这三个延迟函数均是忙等待函数,因而在延迟过程中无法运行其他任何任务。
三、定时器
任何通过定时器函数访问的数据结构都应该针对并发访问进行保护。
3.2、tasklet(小任务)和queue机制:
HZ值是一个与体系结构有关的常数。其值表示每秒有多少次时钟中断。
每次当时钟中断发生时,内核内部计数器的值就增加1,这个计数器的值在系统引导时被初始化为0,因此,它的值就是自上次操作系统引导以来的时钟滴答数,这个计数器是一个64位的变量(即使在32位架构上也是64位),称为“jiffies_64”,但是驱动程序开发者通常访问的是jiffies变量,它是unsigned long型变量,要么和jiffies_64相同,要么仅仅是jiffies_64的低32位,通常首选使用jiffies,因为它的访问很快,从而对64位jiffies_64值的访问并不需要在所有架构上都是原子的。jiffies和jiffies_64均应被看作只读变量。
点击(此处)折叠或打开
- #include <linux/jiffies.h>
- unsigned long j, stamp_1, stamp_half, stamp_n;
- j = jiffies;//读取当前值
- stamp_1 = j + HZ; //未来1秒
- stamp_half = j+ HZ / 2;//半秒
- stamp_n = j + n *HZ / 1000;//n毫秒
点击(此处)折叠或打开
- #include <linux/jiffies.h>
- int time_after(unsigned long a, unsigned long b);
- int time_before(unsigned long a, unsigned long b);
- int time_after_eq(unsigned long a, unsigned long b);
- int time_before_eq(unsigned long a, unsigned long b)
用等待队列实现延时:
点击(此处)折叠或打开
- wait_queue_head_t wait;
- init_waitqueue_head(&wait);
- wait_event_interruptible_timeout(wait, 0, delay);
点击(此处)折叠或打开
- #include <linux/delay.h>
- void ndelay(unsigned long nsecs);
- void udelay(unsigned long usecs);
- void mdelay(unsigned long msecs);
三、定时器
3.1、内核timer定时器
首先需要定义一个timer_list变量timer
先初始化timer:
init_timer(&timer);
然后对timer的相关参数赋值:
timer.function = fun;
timer.expires = jiffies + TIMER_DELAY;
timer.data = (unsigned long)dev;
add_timer(&timer);
在定时器时间到的时候,会执行fun,如果继续定时,可以通过在fun中执行:
mod_timer(&timer, jiffies + TIMER_DELAY);
在不需要的时候通过调用:
del_timer(&timer);删除定时器。
这样一个简单的定时器就完成了。
内核定时器常常是作为“软件中断”的结果而运行的。在这种原子性的上下文中运行时,代码会受到许多限制,定时器函数必须以原子方式运行。任何通过定时器函数访问的数据结构都应该针对并发访问进行保护。
点击(此处)折叠或打开
- include <linux/timer.>
- struct timer_list {
- struct list_head list;
- unsigned long expires;
- unsigned long data;
- void (*function)(unsigned long);
- };
在第十章中讲述。