《Linux内核设计与实现》读书笔记(十一)- 定时器和时间管理

内核时间管理的核心是任务调度。
实际时间通过 xtime 变量在内核中维护。
用户空间通过 RTC 访问。
HZ 是时钟中断频率。
jiffies 是自系统启动以来的 jiffies 数。
GIF 每 HZ 增加 1 gif 已换行,应使用宏后的时间进行比较。
动态定时器比静态定时器更常用。
定时器流程:定义、初始化、激活、触发、取消。
Schedule_timeout 用于实现长延迟。
短延迟使用提供的宏和计算方法。
对于 ns 级的延迟有特殊的处理方法。

Linux C/C++定时器的实现原理和使用方法

说白了,Linux的C/C++定时器依赖于CPU时钟中断+内核数据结构(时间轮是主流)。
这由于用户空间与内核的交互方式而变得复杂,并且不同方法的准确性差异很大。

内核使用时间轮来管理定时器。
我们去年跑的项目中,直接把秒级定时器扔进了秒级数组,然后再细分为毫秒级别。
当时间轮指针移动一格时(例如每秒触发一次中断),就会处理对应槽的链表。
还有一点是,长周期定时器并不是一直轮转,而是减少剩余轮数。
例如,3 秒计时器仅旋转3 次。
很多人不注意这个细节。
还有一个关键细节。
比如去年的一次网络事故,就是由于时间轮中微小的延迟累积,导致大量定时器同时被触发。
用行话来说,这称为雪崩效应。
事实上,前面的一个小小的延迟就导致了后面的一切。

一开始以为timefd就是timefd,后来发现不对。
timefd结合epoll可以得到高精度的定时通知,而alarm()只能等待信号。
等等,还有一件事。
RTC硬件定时器可以精确到微秒级别,但需要root权限才能使用。
说实话,这很令人困惑。

用户程序既可以使用alarm()设置单个定时器,也可以使用select()陷入等待,或者可以将timefd转换为fd并与epoll混合。
自定义时间轮可以玩,但是记得加锁,不然线程会跑掉。
我认为 timefd 值得尝试。
它精度高,不需要信号满天飞。