内核定时器是一个数据结构,它告诉内核在用户定义的时间点使用用户定义的参数来执行一个用户定义的函数。其实现位于
<linux/timer.h>中。
内核提供了一组用来声明、注册和删除内核定时器的函数,相关接口如下:
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;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
//定时器动态初始化
void init_timer(struct timer_list &timer);
//定时器静态初始化
#define DEFINE_TIMER(_name, _function, _expires, _data)
//添加定时器
void add_timer(struct timer_list *timer);
//删除定时器
int del_timer(struct timer_list * timer);
//和上面类似,但该函数可确保在返回时没有任何CPU在运行定时器函数
int del_timer_sync(struct timer_list *timer);
//修改定时器
int mod_timer(struct timer_list *timer, unsigned long expires);
//检查定时器是否正在被调度运行
int timer_pending(const struct timer_list * timer);
下面给出定时器使用的小栗子,定时器以斐波那契数列为参数,当定时时间达到13秒时自动退出:
/*
* Description : 内核定时器demo
* Author : mason
* Date : 201808
*/
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static unsigned long data;
struct timer_list demo_timer;
/* 斐波那契数列 */
unsigned long fibonacci(unsigned long data)
{
if (data == 1 || data == 2)
{
return 1;
}
else
{
return fibonacci(data-1) + fibonacci(data-2);
}
}
/* 定时器回调函数 */
void timer_handler(unsigned long arg)
{
unsigned long intv;
printk("current fibonacci is : %lu \r\n", arg);
if (arg == 13)
{
printk("Game Over Bye\r\n");
del_timer(&demo_timer);
return ;
}
else
{
data++;
intv = fibonacci(data);
/* HZ单位为秒 */
demo_timer.expires = intv * HZ + jiffies;
demo_timer.data = intv;
/* 重新添加定时器 */
add_timer(&demo_timer);
return;
}
}
static int __init timer_demo_init(void)
{
printk("Hello timer\r\n");
data = 1;
/* 定时器初始化 */
init_timer(&demo_timer);
demo_timer.expires = data * HZ + jiffies;
demo_timer.data = data;
demo_timer.function = timer_handler;
add_timer(&demo_timer);
return 0;
}
static void __exit timer_demo_exit(void)
{
printk("Bye timer\r\n");
return ;
}
module_init(timer_demo_init)
module_exit(timer_demo_exit)
MODULE_AUTHOR("mason");
MODULE_DESCRIPTION("netlink kernel test");
MODULE_LICENSE("GPL");
Makefile:
obj-m := timer_demo.o
PWD := $(shell pwd)
KERNEL_DIR := "/usr/src/linux-headers-"$(shell uname -r)/
modules:
@$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
@rm -rf *.ko *.o *.mod.c *symvers *order .nl* .tmp*
内核版本 : 3.4.39
运行截图:
参考资料 :
1. 《LInux 设备驱动程序第三版》
2. 《深入理解Linux内核》