linux的定时测量分析
定时测量之前的文章学习中的初步印象,是由特殊的电路系统上报给操作系统的一种信号量。下面是《深入理解Linux内核》一书中的阐述和思考。
定时测量
操作系统中需要处理的定时测量主要是两种:
- 测量当前的日期和时间
- 维持定时器,以便测量出某一时间间隔
定时测量是通过一种基于固定的频率振荡设备和计数器设备来实现的,下面介绍一下这几个硬件设备。
时钟和定时器电路
- 实时时钟-RTC
实时时钟(Renl Time Clock RTC)是一个独立于CPU和其他芯片的设备,即使当计算设备被切断电源时,它还是还能正常工作。

在现代的计算机结构中,RTC设备通常被集成到南桥中
- 时间戳计数器-TSC
时间戳计数器是用来接收外部传递的振荡器的时钟信号。在x86架构下是通过一条名叫CLK的输入总线和一个名叫时间戳计时器寄存器来实现的。
-
可编程间隔定时器-PIT
PIT与RTC类似,也是一个独立于CPU和其他芯片的设备,但是它的工作方式与RTC不同。PIT是通过按照固定的频率发送一个特殊的中断信号来实现的。 -
CPU本地定时器
CPU本地定时器的工作原理与PIT类似都是发送一个特殊的中断信号,但是不同点在于,CPU本地定时器是据语系统总线的时钟信号量的值来实现的。
- 高精度事件定时器-HPET
高精度事件定时器是由MS与Intel共同研发的一种新型定时器,目前应该是支持最广泛的定时器,内部主要包括8个32位或64位的独立计数器,在windows下通过设备管理器插看到

在参考资料2中可以看到时钟频率对游戏帧率的影响,游戏帧率越高,时钟频率越低,这样的话,游戏的性能就会越好。这里的原理类似于显示屏幕的物理帧率对游戏性能的影响一样,可以看一下B站Up主的一个视频游戏帧数竟然可以影响永劫的攻击速度?!
- ACPI定时器
ACPI电源管理定时器几乎存在所有的ACPI主板上,它是一个简单的计数器,每次时钟节拍到来时,寄存器就加1.
以上是一些定时器的简单介绍,主要有RTC、HPET
Linux计时体系结构
linux启动后必须执行的与时间相关的操作是以下几个:
- 更新系统启动以后经过的时间
- 更新当前日期和时间
- 确定当前进程在每一个CPU上运行的时间
- 更新资源使用统计数量
-检查每一个软件定时器的时间间隔是否达到
在多处理器系统中,每一个CPU都有一个时钟,它的频率可以被设置,默认的频率是1GHz,也就是说,每秒钟的时钟节拍数是1000000。普通活动(例如:软定时器)都是由全局定时器产生的中断触发的;CPU的活动则是由本地的APIC产生的中断触发的。
(PS:APIC与ACPI的区别,ACIP是本地CPU定时器,而APIC是全局电源方面的定时器,优先级较高)
内核会提供两个最基本的计时函数:一个保持对当前时间的记录,一个计算当前秒内流逝的纳秒数
- 计时体系的数据结构
这里主要介绍一个jiffies变量,这个变量是用于记录系统启动后产生的节拍数,但是在X86架构下这个变量使用的是一个32位置的有符号值,因此大约只需要50天左右就会置为0,这被称为时钟回绕问题,linux提供了time_after和time_before函数来解决这个问题。解决问题的思路是通过先将32位的数据转化为64位的long类型来比较,这样做的原理是,当32位的数据转化为64位的long类型后,其符号位会被置为0,从一个有符号数变成了无符号数,在对差值与0进行比较,就可以解决时钟回绕问题。
关于这个jiffies变量还有一个指的注意的地方是,它在初始化时,并不是赋的0,而是负3W多的一个数字,这样做的目的是尽早的发现时钟回绕问题是否被正确的处理,这里面实际体现了一种不可靠思想,想尽量的让问题尽早的暴露出来,指的学习!
jiffies变量为什么选择的是32位而不是64位,这里主要是因为在32位系统中对64位数值的访问需要使用两个32位数值来处理,这样操作两次比直接操作32位的数值要慢一些
定时测量的应用
- 更新日期和时间
- 更新系统统计数据,例如CPU统计数、系统负载等
- 监管内核代码,例如每次时钟中断时判断当前系统正在做什么
- 检查非屏蔽中断监视器,监控系统内核的运行情况
- 软定时器与延迟函数
小结
Linux的定时测量是通过不同的硬件来实现的,有记录当前时间的RTC、有记录系统启动时间的TSC、有记录CPU的时钟周期的APIC、有记录全局时间的电源定时器ACPI、记录高精度时间的HPET等。操作系统通过这些定时器来实现记录系统运行状态、记录当前时间、记录流逝时间等功能。
参考资料
ubuntu RTC驱动说明书
如何通过禁用 HPET 设置来提高游戏性能
ACPI和APIC有什么关系
jiffies如何避免时钟回绕问题