一、内核时间管理
硬件定时器提供时钟源,linux内核中在图形化界面配置中可以配置,我们选择最低的系统频率100Hz,使得内核负载减小。也就是说一秒钟可以产生100次中断。
在Linux内核中以全局变量jiffies记录系统从启动以来的节拍数。如果系统频率1000Hz是64位的操系统,系统超过5.8亿年就会归0,所以不用考虑绕回问题。但是32位系统,只要49天定时器就会溢出二造成绕回现象。内核提供了处理绕回的API函数。
函数 | timeout = jiffies + (2 * HZ) |
---|---|
time_before(jiffies, timeout) | 判断没超过 |
time_after(jiffies, timeout) | 判断超过 |
time_after_eq(jiffies, timeout) | |
time_before_eq(jiffies, timeout) |
系统还提供了jiffies的互转函数,转换为ms,us,ns
二、内核定时器
1.定时器结构体
声明include/timer.h内。核定时器当定时时间到了以后就会关闭。使用定时器就要使用timer_list结构体定义的变量。expires成员是定时的时间;function函数指针是指向定时器的定时处理函数;data成员是function的参数。
struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct list_head entry;
unsigned long expires;
struct tvec_base *base;
void (*function)(unsigned long);
unsigned long data;
int slack;
};
2.定时器的API
函数 | 说明 |
---|---|
void init_timer(struct timer_list *timer) | 初始化定时器 |
void add_timer(struct timer_list *timer) | 添加定时器 |
int del_timer(struct timer_list * timer) | 删除定时器 |
int del_timer_sync(struct timer_list *timer) | 同步删除定时器 |
int mod_timer(struct timer_list *timer, unsigned long expires) | 修改定时器 |
注意:
add_timer函数执行以后,timer对象就开始对jiffies计数器开始计数了。
mod_timer是对timer定时器的重新修改,并且开始从新开始计数,也就是“回绕”
三、编写驱动
1.创建timer设备
2.初始化定时器Timer。
①定义定时器变量
②定时器设置函数指针,定时时间
3.编写定时器中断函数。
①输出信息
②绕回设置mod_timer。
#include<linux/timer.h>
#include<linux/jiffies.h>
/*设备结构体*/
struct timer_dev{
dev_t devid; /*设备号*/
int major; /*主设备号*/
int minor; /*次设备号*/
struct cdev cdev; /*字符设备*/
struct class *class; /*设备的类*/
struct device *device;/*设备*/
struct device_node *nd;/*设备结点*/
struct timer_list timerdev; /*Timer*/
};
struct timer_dev timer;
/*
Timer中断处理函数
*/
static void timer_handler(unsigned long dummy){
static int i = 0;
struct timer_dev *dev = (struct timer_dev*)dummy;
printk("i = %d \r\n" , i++);
//达到绕回的问题
mod_timer(&dev->timerdev , jiffies + msecs_to_jiffies(1000));
}
/* 初始化定时器 */
init_timer(&timer.timerdev);
timer.timerdev.expires = jiffies + msecs_to_jiffies(1000); //定时1s
timer.timerdev.function = timer_handler;
timer.timerdev.data = (unsigned long)&timer;
add_timer(&timer.timerdev); //添加到系统