内核定时器 -32
Posted 杨斌并
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核定时器 -32相关的知识,希望对你有一定的参考价值。
内核定时器
Linux内核定时器概念
不同于单片机定时器,Linux内核定时器是一种基于未来时间点的计时方式,以当前时刻为启动的时间点,以未来的某一时刻为终止点。比如,现在是10点5分,我要定时5分钟,那么定时就是10点5分+5分钟=10点10分。这个和咱们的手机闹钟很类似。比如你要定一个第二天早晨的8点的闹钟,就是当前时间定时到第二天早晨8点。
需要注意的是,内核定时器定时精度不高,不能作为高精度定时器使用。并且内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那么就需要在定时处理函数中重新开启定时器。
Linux内核定时器基础知识
Linux内核使用timer_list 结构体表示内核定时器,timer_list定义在文件include/linux/timer.h中,
定义如下:
struct timer_list {
struct list_head entry;
unsigned long expires;/*定时器超时时间,不是时长,单位是节拍数*/
struct tvec base *base;
void (*function)(unsigned long); /*定时处理函数*/
unsigned long data; /*要传递给 function 函数的参数*/
int slack;
}
在这个结构体中,有几个参数我们需要重点关注一下。
-
一个是expires到期时间,单位是节拍数。等于定时的当前的时钟节拍计数(存储在系统的全局变量jiffies)+定时时长对应的时钟节拍数量。
-
那么我怎么把时间转换成节拍数量呢?
示例:从现在开始定时1秒:
-
内核中有一个宏 HZ,表示一秒对应的时钟节拍数,那么我们就可以通过这个宏来把时间转换成节拍数。所以,定时1秒就是:expires = jiffies + 1*HZ。
-
HZ的值我们是可以设置的,也就是说一秒对应的时钟拍数我们是可以设置的,Linux内核会使用 CONFIG_HZ来设置自己的系统时钟。打开文件include/asm-generic/param.h,有如下内容:
#define undef HZ
#define HZ CONFIG_HZ
#define USER HZ 100
宏HZ就是CONFIG HZ,因此 HZ=100,表示一秒的节拍数是100,们在编译 Linux内核的时候可以通过图形化界面设置系统节拍率,按照如下路径打开配置界面。
make meunconfig
kernel features Timer frequency //路径
-
可选的系统节拍率为100Hz、200Hz、250Hz、300Hz、500Hz 和1000Hz。默认是100Hz。
-
第二个我们需要关心的参数是function超时处理函数,这个并不是硬件中断服务程序。原型:
void function(unsigned long data);
-
第三个参数是data传递给超时处理函数的参数,可以把一个变量的地址转换成unsigned long .
Linux内核定时器相关操作函数(#include <linux/timer.h>)
时间转换函数
- ms转换为时钟节拍函数
unsigned long msecs_to_jiffies(const unsigned int m)
- us转换为时钟节拍函数
unsigned long usecs_to_jiffies(const unsigned int u)
举例:
定时10ms
计算: jiffies + msecs_to_jiffies(10)<2>定时10us
计算: jiffies + usecs_to jiffies(10)<2>宏DEFINE_TIMER
原型:
#define DEFINE_TIMER(_name,_function,_expires,_data)
作用:
静态定义结构体变量并且初始化初始化function, expires, data 成员。
参数:
- name变量名;
- function超时处理函数;
- data传递给超时处理函数的参数
- expires到点时间,一般在启动定时前需要重新初始化。
- add_timer函数
原型:
void add_timer(struct timer_list*timer)
作用:
add_timer函数用于向Linux内核注册定时器,使用add_timer函数向内核注册定时器以后,定时器就会开始运行
参数:
- timer:要注册的定时器。
- del_timer函数
原型:
int del_timer(struct timer_list * timer)
作用:
del_timer函数用于删除一个定时器,不管定时器有没有被激活,都可以使用此函数删除。在多处理器系统上,定时器可能会在其他的处理器上运行,因此在调用del_timer函数删除定时器之前要先等待其他处理器的定时处理器函数退出
参数:
- timer:要删除的定时器。
- 返回值: 0,定时器还没被激活;1,定时器已经激活。
- mod_timer.函数
函数原型:
int mod_timer(struct timer_list *timer, unsigned long expires)
作用:
mod_timer 函数用于修改定时值,如果定时器还没有激活的话, mod_timer 函数会激活定时器!
参数:
- timer:要修改超时时间(定时值)的定时器。expires:修改后的超时时间。
- 返回值:0,调用mod_timer函数前定时器未被激活;1,调用mod_timer函数前定时器已被激活
代码
- helloworld.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
static void timer_function(unsigned long data);
DEFINE_TIMER(test_timer, timer_function, 0, 0);
static void timer_function(unsigned long data){
printk("timer_function \\n");
mod_timer(&test_timer, jiffies + 1*HZ);
}
static int hello_init(void){
printk(KERN_EMERG "hello world enter \\n");
test_timer.expires = jiffies + 1*HZ;
add_timer(&test_timer);
return 0;
}
static void hello_exit(void){
printk(KERN_EMERG "hello world exit! \\n");
del_timer(&test_timer);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LIYU");
以上是关于内核定时器 -32的主要内容,如果未能解决你的问题,请参考以下文章