了解Linux的定时器的工作原理,有助于我们更深刻的认识Node中的定时器真面目。
定时器核心组件
- 石心 - 时钟源 - 硬件
- 守护者 - 记录时间 - 软件
- 定时狗 - 事件源 - 硬件
石心
硬件层面上有两个主要的模块: CMOS 和 CPU。 CMOS 可以在断电后继续振动
和更新RTC
时间, CPU上电后在TSC寄存器
可以在记录上电后
的cycles总和,其本质只是一个收到高电压后+1的Counter
。
此时操作系统可以获取到: RTC, TSC, Frequecy,那么系统的时间就可以通过公式
计算出来: RTC + TSC/Frequency
硬件的缺陷
:
CMOS: RTC 是整个系统初始化
的时间,但其本身精度较低
,毫秒级,所以多台机器时钟很难在毫秒以下对齐
TSC: TSC 精度虽然可以在纳秒
级别,但是只能记录上电之后的时间;TSC 通过64位存储,在10GHz情况下,溢出
时间为2**64/(1e10*3600*24*365)≈58Y
守护者
ClockSource是对硬件TSC
的一种抽象,可以通过 read 方法读取到 TSC 寄存器中的 cycle,然后将cycle赋值给自身,只是在没有调用read方法之前,其时间落后
于真正的TSC。
目前最高精度的硬件: tsc > hpet > acpi_pm, 他们都是时间记录者,里面存储的是cycle.
#$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm
#$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
TimeKeeper 的主要工作就是主动调用
ClockSource中的read,然后做cycle到timestamp的转换(时间到时刻的转换
),并记录到自身。此时操作系统读取的时间就是从TimeKeeper中读取。
管家的缺陷:
TimeKeeper 只是时间的抽象,没有办法实现时间的自动更新
,需要外部调用
更新,所以时间落后于真正的TSC。
定时狗
无论是ClockSource还是TimerKeepr,他们只是对数字的一抽象,没有办法主动更新, 所以为了保持时间的实时性,需要一个程序不断的调用 read 来更新时间.
结合定时器: 石心中的内容,一个自更新的时间的原型大概是这样的:
while(true) {
const cycles = TimeKeeper.ClockSOurce.read(tsc);
const now = TimeKeeper.setTimer(cycles);
if (now != '双11') {
schedule(); // 让CPU干点其他的,等会在更新时间,毕竟时间不能当饭吃
}
}
优惠();
该定时器的问题是: 无法控制CPU回调的时间,可能超时;频繁CPU调度。
软件与硬件必须互相配合,上面的问题在没有硬件加持下是无法避免的,所以需要引入一个非常中的硬件APIC 高级可编程中断控制
。
目前最牛X的APIC为: lapic-deadline,而ClockeEventDevice就是对APIC硬件的抽象。
#$ cat /sys/devices/system/clockevents/clockevent0/current_device
lapic-deadline
之所以说它最牛,是因为它本身就是一个(硬件)定时器: 可以给apic设定一个超时的cycle数量,当TSC中的cycle到达该值时,发送一个事件
。
有了基于cycle(精度)的事件(通知),实现高精度定时器就不在话下了;低精度定时器完全也可以通过高精度定时器来模拟出来。
总结
- CMOS中的RTC提供初始化时刻
- CMOS中的晶体提供震荡
- CPU中的TSC寄存器只记录上电以来的震荡个数cycle
- CPU中的APIC可以根据预设的cycle产生事件
硬件和软件相辅相成,需要效率支撑的通过硬件来支撑,硬件缺失的情况下可以通过软件来模拟。
关注我的微信公众号“SUNTOPO WLOG”,欢迎留言讨论,我会尽可能回复,感谢您的阅读。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!