赞
踩
内核使用绝对时间来了解具体的时间,也就是一天的日期和时间,而相对时间则被内核调度程序使用。对于绝对时间,有一个称为实时时钟的硬件芯片(RTC)。
内核定时器有两种
标准定时器
标准定时器是内核定时器,它以jiffy为粒度运行。
常量HZ是jiffies在1s内递增的次数,每个增量被称为一个Tick。
定时器API
定时器在内核中表示为timer_list的一个实例
struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct hlist_node entry;
unsigned long expires;
void (*function)(struct timer_list *);
u32 flags;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
expires
以jiffies为单位,function为回调函数。
初始化定时器
/**
* timer_setup - prepare a timer for first use
* @timer: the timer in question
* @callback: the function to call when timer expires
* @flags: any TIMER_* flags
*
* Regular timer initialization should use either DEFINE_TIMER() above,
* or timer_setup(). For timers on the stack, timer_setup_on_stack() must
* be used and must be balanced with a call to destroy_timer_on_stack().
*/
#define timer_setup(timer, callback, flags) \
__init_timer((timer), (callback), (flags))
#define timer_setup_on_stack(timer, callback, flags) \
__init_timer_on_stack((timer), (callback), (flags))
/** * mod_timer - modify a timer's timeout * @timer: the timer to be modified * @expires: new timeout in jiffies * * mod_timer() is a more efficient way to update the expire field of an * active timer (if the timer is inactive it will be activated) * * mod_timer(timer, expires) is equivalent to: * * del_timer(timer); timer->expires = expires; add_timer(timer); * * Note that if there are multiple unserialized concurrent users of the * same timer, then mod_timer() is the only safe way to modify the timeout, * since add_timer() cannot modify an already running timer. * * The function returns whether it has modified a pending timer or not. * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an * active timer returns 1.) */ int mod_timer(struct timer_list *timer, unsigned long expires) { return __mod_timer(timer, expires, 0); } EXPORT_SYMBOL(mod_timer);
/** * del_timer - deactivate a timer. * @timer: the timer to be deactivated * * del_timer() deactivates a timer - this works on both active and inactive * timers. * * The function returns whether it has deactivated a pending timer or not. * (ie. del_timer() of an inactive timer returns 0, del_timer() of an * active timer returns 1.) */ int del_timer(struct timer_list *timer) { struct timer_base *base; unsigned long flags; int ret = 0; debug_assert_init(timer); if (timer_pending(timer)) { base = lock_timer_base(timer, &flags); ret = detach_if_pending(timer, base, true); raw_spin_unlock_irqrestore(&base->lock, flags); } return ret; } EXPORT_SYMBOL(del_timer);
对于不活动的定时器,返回0,对于活动的定时器,返回1。
/** * del_timer_sync - deactivate a timer and wait for the handler to finish. * @timer: the timer to be deactivated * * This function only differs from del_timer() on SMP: besides deactivating * the timer it also makes sure the handler has finished executing on other * CPUs. * * Synchronization rules: Callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from * interrupt contexts unless the timer is an irqsafe one. The caller must * not hold locks which would prevent completion of the timer's * handler. The timer's handler must not call add_timer_on(). Upon exit the * timer is not queued and the handler is not running on any CPU. * * Note: For !irqsafe timers, you must not hold locks that are held in * interrupt context while calling this function. Even if the lock has * nothing to do with the timer in question. Here's why:: * * CPU0 CPU1 * ---- ---- * <SOFTIRQ> * call_timer_fn(); * base->running_timer = mytimer; * spin_lock_irq(somelock); * <IRQ> * spin_lock(somelock); * del_timer_sync(mytimer); * while (base->running_timer == mytimer); * * Now del_timer_sync() will never return and never release somelock. * The interrupt on the other CPU is waiting to grab somelock but * it has interrupted the softirq that CPU0 is waiting to finish. * * The function returns whether it has deactivated a pending timer or not. */ int del_timer_sync(struct timer_list *timer);
等待处理程序(即使在另一个cpu上执行)执行完成,不应该持有阻止处理程序完成的锁,这样会导致死锁,应该在模块清理流程中释放定时器,可以独立检查定时器是否在运行。
/**
* timer_pending - is a timer pending?
* @timer: the timer in question
*
* timer_pending will tell whether a given timer is currently pending,
* or not. Callers must ensure serialization wrt. other operations done
* to this timer, eg. interrupt contexts, or other CPUs on SMP.
*
* return value: 1 if the timer is pending, 0 if not.
*/
static inline int timer_pending(const struct timer_list * timer)
{
return !hlist_unhashed_lockless(&timer->entry);
}
注册定时器之后,在timer_callback()修改定时器的延时时间,这个是第一种方式实现,大家可以尝试使用add_timer()方式实现。
#include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/kernel.h> //毫秒 #define TIMEOUT 5000 //定义定时器 struct timer_list mytimer; unsigned int count = 0; //定时器处理函数 mod_timer(&mytimer, jiffies + TIMEOUT); static void timer_callback(struct timer_list *data) { printk("Timer Callback function Called [%d]\n", count++); mod_timer(&mytimer, jiffies + msecs_to_jiffies(TIMEOUT)); } //定时器初始化过程 static int __init timer_init(void) { /* 初始化一个定时器 */ timer_setup(&mytimer, timer_callback, 0); /* 修改定时器的延时时间 */ mod_timer(&mytimer, jiffies + msecs_to_jiffies(TIMEOUT)); return 0; } static void __exit timer_exit(void) { /* 卸载驱动移除注册的定时器 */ del_timer(&mytimer); } module_init(timer_init); module_exit(timer_exit); MODULE_AUTHOR("curtis"); MODULE_LICENSE("GPL");
没有 current 指针、不允许访问用户空间。因为没有进程上下文,相关代码和被中断的进程没有任何联系。
不能执行休眠(或可能引起休眠的函数)和调度。
任何被访问的数据结构都应该针对并发访问进行保护,以防止竞争条件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。