一、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均应被看作只读变量。
-
#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)
如果a(jiffies的某个快照)所代表的时间比b靠后,则第一个宏返回真;如果a比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);
-
};
3.2、tasklet(小任务)和queue机制:
在第十章中讲述。
阅读(3178) | 评论(0) | 转发(0) |