梦开始的地方
X86硬件时钟
首先我们需要了解一下,目前有哪些时钟
PIT
pit是最古老的pc时钟设备。Intel 8253/8254 PIT是具有3个16位计数器通道的可编程计数/定时器芯片,晶振频率为1.193182MHz。
HPET
PET(High Precision Event Timer)俗称高精度定时器(到时了产生中断),最低时钟频率为10MHZ,而且定义了比较严格的精确度。HPET设计时是为了替代PIT和RTC,但是现在PIT和RTC在一些系统中还是有应用的价值。
Apic timer
多处理器系统中,每个处理器都有一个Local APIC。现在Local APIC已经集成到处理器芯片中。Local APIC带有一个timer。它的频率与内存总线频率有关,所以软件不能直接获取它的频率值。一般在启动时通过PIT/Hpet来计算校准Local APIC的频率。
CMOS RTC
CMOS RTC需要电池供电的计时芯片,当操作系统关机后,RTC可以继续计数。RTC提供了year/month/day hour:minute:second的时间格式,精度为秒。它也可以产生频率为2Hz~8192Hz频率的周期性时钟中断。另外提供了两种中断:Update Interrupt和alarm Interrupt,系统可以选择是否使能。Update Interrupt每秒产生一次,Alarm Interrupt在RTC时间到了设置的时间时产生。
TSC
TSC是64bit的cycle计数器,根据CPU的时钟振荡器产生的周期计数。TSC不能产生中断。软件可以通过指令(rdtsc/rdtscp)来获取TSC计数值。跟APIC timer一样,软件不能直接获取TSC的输入频率,只有通过使用PIT/CMOS timer 来计算校准TSC的频率。
ACPI Timer
ACPI timer又称Power management timer(PM timer),是ACPI提供的定时器。它有一个以3.57945MHz频率(PIT时钟频率的3倍)向上计数的24位的计数寄存器,但没有计数设置寄存器。每当计数达到最大值时,计数又从0开始递增计数。
LINUX时钟体系结构
clock source:时钟源,硬件设备的抽象
Clock events:时钟事件信息,包括硬件中断发生要执行哪些操作
Timekeeper:Timekeeping子系统负责更新xtime调整误差,及提供get/settimeofday接口
TickDevices: 对clock events设备的进一层封装,用于代替时钟滴答中断,给内核提供 tick 事件
LINUX时钟和时间
墙上时间和系统时间
墙上时间(wall-clock):从00:00:00GMT,1 january 1970开始的时间
系统时间(System time):系统启动后经过的时间。可以用jiffies来换算
时钟中断:
(1)更新系统启动后的时间流逝
Linux中用全局变量jiffies表示系统自启动以来时钟滴答数目(中断个数)
(2)更新墙上时间(wall-clock)
Linux内部用xtime来表示,从某一历史时刻开始到现在的时间。Update_wall_time()
(3)计算进程的时间片
(4)更新资源计数
(5)引发软件定时器
LINUX时钟初始化顺序
APIC时钟校验流程
虚机系统中lapic时间校验失败分析
先使用被htep校验过频率的tsc计算lapic的频率
使用lapic频率设置period中断,检测lapic发送10次中断前后的jiffies值大小
目前jiffies普遍偏大,在jiffies时钟源不变的情况下,说明设置apic中断和接收中断并处理花费的时间较多
根因
在hypervisor(HAXM/KVM)中耗时较多,现实时间流逝较多导致guest认为10次中断到来的时间超过应该增加的jiffies数量,故认为始终不可信而放弃使用