内核定时器timer_list
内核在时钟中断发生后执行检测各个定时器是否到期,到期后的定时器处理函数将作为软中断在底半部执行。实质上,时钟中断处理程序会唤起TIMER_SOFTIRQ软中断,运行当前处理器上到期的所有定时器。linux提供的内核定时器数据结构为timer_list。
一. 定义
timer_list定义在linux/timer.h中,实现在kernel/timer.c中。
struct timer_list { struct list head_entry; unsigned long expires; //到期时间 struct tves_base *base; void (*func)(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 };
内核相关定义:HZ和jiffies
HZ 时钟频率
jiffies 32位无符号数,当前时钟计数
# define HZ CONFIG_HZ /* Internal kernel timer frequency */ # define USER_HZ 100 /* some user interfaces are */
linux/jiffies.h /* * The 64-bit value is not atomic - you MUST NOT read it * without sampling the sequence number in jiffies_lock. * get_jiffies_64() will do this for you as appropriate. */ extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies; #if (BITS_PER_LONG < 64) u64 get_jiffies_64(void); #else static inline u64 get_jiffies_64(void) { return (u64)jiffies; } #endif
二. 函数
初始化定时器
init_timer(&mytimer);
DEFINE_TIMER(_name, _function, _expires, _data);
TIMER_INITIALIZER(_function, _expires, _data);
setup_timer(timer, fn, data);
首次使能定时器
add_timer(&mytimer);
再次使能定时器
mod_timer(&mytimer, unsigned long expires);
删除定时器
del_timer_sync(&mytimer); //删除前要等待定时器处理完,不能发生在中断上下文。
del_timer(&mytimer); //删除定时器
三. 示例
#include <linux/init.h> #include <linux/module.h> #include <asm/current.h> #include <linux/timer.h> #inlcude <linux/sched.h> MODULE_LISENCE("GPL"); extern struct task_struct *current; struct timer_list mytimer; void timer_handler(unsigned long arg) { printk("timer arg = %d\n", arg); mod_timer(&mytimer, jiffies + HZ * 5); return; } static int __init akae_init(void) { int local = 0; printk("module name is %s\n", KBUILD_MODNAME); printk("akae_init at %p\n", akae_init); printk("jiffies at %p\n", &jiffies); printk("jiffies is %ld\n", jiffies); printk("The process is \"%s\" (pid %i)\n", current->name, curent->pid); init_timer(&mytimer); printk("HZ is %d\n", HZ); mytimer.expires = jiffies + HZ * 5; mytimer.function = timer_handler; mytimer.data = 100; add_timer(&mytimer); return 0; } static void __exit akae_exit(void) { printk("module eixt.\n"); printk("akae_exit at %p\n", akae_exit); del_timer_sync(&mytimer); return; } module_init(akae_init); module_exit(akae_exit);