浅谈Linux内核定时器 - 极悦
首页 课程 师资 教程 报名

浅谈Linux内核定时器

  • 2020-12-17 17:53:38
  • 1327次 极悦

Linux内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 <Linux/timer.h> 和 kernel/timer.c 文件中。无论是从单片机还是到后面的多任务系统,还是RTOS到Linux,都需要用到定时器。

 

首先我们要知道被调度的函数肯定是异步执行的,它类似于一种“软件中断”,而且是处于非进程的上下文中,所以调度函数必须遵守以下规则:

1) 没有 current 指针、不允许访问用户空间。因为没有进程上下文,相关代码和被中断的进程没有任何联系。

 

2) 不能执行休眠(或可能引起休眠的函数)和调度。

 

3) 任何被访问的数据结构都应该针对并发访问进行保护,以防止竞争条件。

而内核定时器的调度函数运行过一次后就不会再被运行了(相当于自动注销),但可以通过在被调度的函数中重新调度自己来周期运行。

在SMP系统中,调度函数总是在注册它的同一CPU上运行,以尽可能获得缓存的局域性。

 

1.Linux内核定时器的数据结构:

struct timer_list {

    struct list_head entry;

    unsigned long expires;

    void (*function)(unsigned long);

    unsigned long data;

    struct tvec_base *base;

    /* ... */

};

其中 expires 字段表示期望定时器执行的 jiffies 值,到达该 jiffies 值时,将调用 function 函数,并传递 data 作为参数。当一个定时器被注册到内核之后,entry 字段用来连接该定时器到一个内核链表中。base 字段是内核内部实现所用的。

 

2.jiffies   

全局变量jiffies用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就是Hz。  

HZ:这个可以认为是一个频率,一秒内系统时钟中断的次数        

Jiffies/HZ:我想知道从系统开机到现在系统运行了多少秒,可以这样计算         jiffies类型为无符号长整型(unsigned long)  

当jiffies的值超过它的最大存放范围后就会发生溢出。对于32位无符号长整型,最大取值为(2^32)-1,即429496795。如果节拍计数达到了最大值后还要继续增加,它的值就会回绕到0。

3.使用定时器步骤

struct timer_list  my_timer_list;//定义一个定时器,可以把它放在你的设备结构中init_timer(&my_timer_list);//初始化一个定时器

my_timer_list.expire=jiffies+HZ;//定时器1s后运行服务程序my_timer_list.function=timer_function;//定时器服务函数add_timer(&my_timer_list);//添加定时器

void timer_function(unsigned long);//写定时器服务函数del_timer(&my_timer_list);//当定时器不再需要时删除定时器del_timer_sync(&my_timer_list);//基本和del_timer一样,比较适合在多核处理器使用,一般推荐使用del_timer_sync

 

4.实例分析#include

#include

#include

#include   /*timer*/

#include   /*jiffies*/

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Qifa");

MODULE_DESCRIPTION("Timer Module");

MODULE_ALIAS("timer module");

 

struct timer_list timer;

 

void timer_function(int para)

{

    static int i = 0;

 

    printk("#########%d########Timer Expired and para is %d !!\n",i++,para);

    printk("jiffies:%lu jiffies/Hz: %lu HZ:%d\n",jiffies,(jiffies/HZ),HZ);

    mod_timer(&timer,jiffies+(2*HZ));    

}

 

 

int timer_init(void)

{

    init_timer(&timer);

    timer.data = 5;

    timer.expires = jiffies + (1 * HZ);

    timer.function = timer_function;

    add_timer(&timer);

 

    return 0;

}

 

 

void timer_exit(void)

{

    del_timer( &timer );

}

 

module_init(timer_init);

module_exit(timer_exit);

 

使用定时器的目的无外乎是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务。只要掌握了这一关键点,就能更好地理解定时器的工作机制,Linux内核定时器也是如此。在本站的Linux教程里还有关于Linux中其他类型的定时器的介绍,感兴趣的小伙伴可以深入学习一下。


选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交