Notes about timer in Linux kernel.内容主要转载自Timer Example

1. Prerequisite

jiffies记录了系统启动以来,经过了多少tick。
一个tick代表多长时间,在内核的CONFIG_HZ中定义。比如CONFIG_HZ=200,则一个jiffies对应5ms时间。所以内核基于jiffies的定时器精度也是5ms。

2. Timer API

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>

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 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:

    1
    int mod_timer(struct timer_list *timer, unsigned long expires);
  • Releasing the timer: When you are done with the timer, it needs to be released:

    1
    2
    int del_timer(struct timer_list * timer);
    int del_timer_sync(struct timer_list *timer);

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:

1
int timer_pending(const struct timer_list * timer);

4. Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>

static struct timer_list my_timer;

static void my_timer_callback(struct timer_list *timer)
{
printk("%s called (%ld)\n", __func__, jiffies);
}

static int __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__);

return 0;
}

static void __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

参考资料:

  1. Timer Example
  2. jiffies背景介绍