1. 用户态定时器
Linux用户态定时器想必大家都有所了解,以下只列出相关API,如:
1) alarm:超时产生SIGALRM信号的那种;
2) 间隔定时器:getitimer、setitimer;
3) timerfd系列:timerfd_create、timerfd_settime、timerfd_gettime;
4) POSIX per-process timer(POSIX每CPU定时器):timer_create、timer_delete、timer_settime、timer_gettime等;
不懂的读者可以翻阅其他文章。
2. 写在kernel定时器之前
了解了用户态定时器相关知识,我们不禁要想:Linux内核是如何进行计时或时间管理的呢?以下将简述内核计时原理和定时器实现方案。
1) HZ
内核通过定时器中断来跟踪时间流,定时器中断由系统定时硬件(如:晶振)以周期性的时间间隔产生,此间隔由内核根据HZ值设置(即每秒产生HZ次中断),HZ是个常量,其值可以在内核编译时通过CONFIG_HZ来设置,一般以250为默认值。如笔者的内核CONFIG_HZ配置值为:
zglinux module_test # cat /boot/config-4.14.0 | grep CONFIG_HZ
# CONFIG_HZ_PERIODIC is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
zglinux module_test #
2) jiffies
除HZ外,内核通过jiffies_64全局变量(64位整型---文件timer.c中)进行时间计数,并通过EXPORT_SYMBOL导出为公共符号。此值表示自系统引导以来系统经历的时钟滴答数。此外,用于历史原因,内核源码还包括另一个时间基准:全局变量jiffies。其在32位系统中为32位整形,而不是64位。内核使用一种技巧来防止两个不同的时间基准转换时引入的精度误差,即将jiffies_64和jiffies的低32位重合。驱动程序一般访问jiffies值,因为其访问更快。
2. 内核定时器
有了jiffies时间计数,内核就可以实现定时器机制了。
1) 数据结构
内核定时器按照hlist链表进行组织,每个定时器实例由如下结构表示:
struct timer_list {
/*
* All fi