- 前言
- 一、内核定时器
- 二、相关的函数
- 1.timer_list结构体
- 2.宏HZ
- 3.宏DEFINE_TIMER
- 4.函数add_timer
- 5.函数del_timer
- 6.函数mod_timer
- 三、代码文件
- 1.timer.c文件
- 2.Makefile文件
- 四、运行结果
- 总结
本文的主要内容是Linux下的内核定时器介绍,包括基本概念和其相关的一些函数介绍,还有一个内核定时器的应用例子。
一、内核定时器
不同于单片机定时器,Linux内核定时器是一种基于未来时间点的计时方式,它以当前时刻为启动的时间点,以未来的某一时刻为终止点,类似于我们的闹钟。
内核定时器的精度不高,不能作为高精度定时器使用,其内核定时器不是周期性运行的,超时以后就会自动关闭,因此要想实现周期性的定时,就需要在定时处理函数中重新开启定时器。
二、相关的函数 1.timer_list结构体
timer_list结构体定义在/linux-4.1.15/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中)+ 定时时长对应的时钟节拍数量。
2.宏HZ内核中有一个宏HZ,表示一秒所对应的节拍数量,可以通过这个宏来把时间转换成节拍数,1秒的表示如下:
expires = jiffies + 1*HZ;
HZ的值也可以自己设置,其定义在/linux-4.1.15/include/asm-generic/param.h文件中。
#ifndef __ASM_GENERIC_PARAM_H #define __ASM_GENERIC_PARAM_H #include# undef HZ # define HZ CONFIG_HZ # define USER_HZ 100 # define CLOCKS_PER_SEC (USER_HZ) #endif
定时10ms:
jiffies + msecs_to_ jiffies(10);
定时10us:
jiffies + usecs_to_ jiffies(10);3.宏DEFINE_TIMER
宏DEFINE_TIMER的原型如下:
DEFINE_TIMER(_name,_function,_expires,_data);
作用:静态定义结构体变量并且初始化function,expires,data成员。
参数介绍:
name:变量名
function:超时处理函数
expires:到期时间,一般在启动定时前需要重新初始化。
data:传递给超时处理函数的参数。
add_timer函数原型如下:
void add_timer(struct timer_list *timer);
作用:向Linux内核注册定时器,注册之后,定时器才会开始运行。
参数介绍:
timer:要注册的定时器。
del_timer函数原型如下:
void del_timer(struct timer_list *timer);
作用:删除一个定时器,不管定时器有没有被激活,都可以使用此函数删除。在多处理器系统上,定时器可能会在其他的处理器上运行,因此在调用该函数删除定时器之前要先等待其他处理器的定时处理器函数退出。
参数介绍:
timer:要删除的定时器。
返回值:返回0表明定时器没有被激活,返回1表示定时器已经激活。
mod_timer函数原型如下:
int mod_timer (struct timer_list *timer,unsigned long expires);
作用:用于修改定时值,如果定时器还没有被激活,该函数可以激活定时器。
参数介绍:
timer:要修改超时时间的定时器。
expires:修改后的超时时间。
返回值:返回0表明调用mod_timer函数前定时器没有被激活,返回1表明调用mod_timer函数前定时器已经激活。
三、代码文件 1.timer.c文件
#include2.Makefile文件#include #include static void timer_function(unsigned long data); DEFINE_TIMER(test_timer,timer_function,0,0); //静态定义结构体变量并且初始化function,expires,data成员 static void timer_function(unsigned long data) { printk("This is timer function!n"); mod_timer(&test_timer,jiffies + 1*HZ); //1秒打印一次 //mod_timer(&test_timer,jiffies + 2*HZ); //2秒打印一次 //mod_timer为超时修改函数,jiffies相当于当前时间,HZ表示一秒对应的时钟节拍数,这里如果不使用该函数,则只打印一次 } static int hello_init(void) { printk("hello world!n"); test_timer.expires = jiffies + 1*HZ; //定义好未来时刻的时间点 add_timer(&test_timer); //向Linux内核注册定时器 return 0; } static void hello_exit(void) { printk("bye!n"); del_timer(&test_timer); //删除定时器 } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
obj-m += timer.o KDIR:=/linux/linux-4.1.15 PWD?=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean
四、运行结果
将上面的代码写好之后编译,然后将驱动发送至开发板,开发板加载驱动后的打印内容如下图所示。
由上图可以看到,打印语句每隔一秒执行一次。
修改代码,使其两秒打印一次,结果如下图所示。
总结
以上就是Linux下内核定时器的所有内容了,重点理解节拍数和时间之间的转换关系。
本文参考视频:https://www.bilibili.com/video/BV1Vy4y1B7ta?p=40。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)