A timer is represented in the kernel as an instance of timer_list:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include<linux/timer.h>
structtimer_list { /* * All fields that change during normal runtime grouped to the * same cacheline */ structhlist_nodeentry; unsignedlong expires; void (*function)(struct timer_list *); u32 flags;
expires is an absolute value in jiffies. entry is a doubley linked list, and a callback function.
3. Timer setup initialization
The following are steps to initialize timers:
Setting up the timer: Set up the timer, feeding the user-defined callback function.
1 2 3 4 5 6 7 8 9 10 11 12
/** * 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))
Setting the expiration time: When the timer is initialized, we need to set its expiration before the callback gets fired:
del_timer() return 0 on an inactive timer, and return 1 on an active timer, del_timer_sync waits for the handler to finish its execution, even those that may happen on another CPU. You should not hold a lock preventing the handler’s completion, otherwise it will result in a dead lock. You should release the timer in the module cleanup routine. You can independently check whether the timer is running or not:
staticvoidmy_timer_callback(struct timer_list *timer) { printk("%s called (%ld)\n", __func__, jiffies); }
staticint __init my_init(void) { int ret; pr_info("%s: Timer module loaded\n", __func__); timer_setup(&my_timer, my_timer_callback, 0); pr_info("%s: Setup timer to fire in 2s (%ld)\n", __func__, jiffies);
ret = mod_timer(&my_timer, jiffies + msecs_to_jiffies(2000)); if (ret) pr_err("%s: Timer firing failed\n", __func__); return0; }
staticvoid __exit my_exit(void) { int ret; ret = del_timer(&my_timer); if (ret) pr_err("%s: The timer is still is use ...\n", __func__); pr_info("%s: Timer module unloaded\n", __func__); }
module_init(my_init); module_exit(my_exit); MODULE_AUTHOR("Yannik Li <yannik520@gmail.com>"); MODULE_DESCRIPTION("Timer example"); MODULE_LICENSE("GPL");
1 2 3 4 5
$ dmesg [1208385.932488] my_init: Timer module loaded [1208385.932581] my_init: Setup timer to fire in 2s (5503072803) [1208387.945145] my_timer_callback called (5503074816) [1208425.037823] my_exit: Timer module unloaded