內核定時器是一個數據結構,它告訴內核在用戶定義的時間點使用用戶定義的參數來執行一個用戶定義的函數。其實現位於
<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內核》