11.LINUX驱动之内核定时器

252 阅读2分钟

一、内核时间管理

硬件定时器提供时钟源,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)修改定时器

三、编写驱动

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);     //添加到系统