被问了 2 个 Question,全都答不上来,汗颜......
1. gettimeofday() 函数的互斥机制?
2. OS 的 tick,如何保证在不同频率的 CPU 上保持一致?
一. 时钟和定时器电路
以固定的、预先定义的频率发出中断。
1. 实时时钟(Real Time Clock, RTC)
独立于 CPU 和其它所有芯片,和 CMOS RAM 集成在一起。能在 IRQ8 上发出周期性的中断,即时钟信号/时钟节拍,频率在 2-8192 Hz 之间。
2. 中断请求(Interrupt Request, IRQ)
3. 时间戳计数器(Time Stamp Counter, TSC)
利用 64 位的时间戳计数器寄存器实现,在每个时钟信号到来时加 1。
使用时,必须考虑时钟信号的频率,例如时钟节拍的频率是 1GHz,那么 TSC 每纳秒增加 1 次。为了做到这一点,Linux 必须在系统初始化期间,算出 CPU 的实际频率,所以同一内核映象可以运行在产生任何时钟频率的 CPU 上。
calibrate_tsc() 函数通过计算一个大约在 5ms 的时间间隔内所产生的时钟信号的个数,来算出 CPU 的实际频率。
通俗一点的理解,芯片(RTC)以固定频率发出中断(IRQ),然后有个计数器(TSC) 在实时计数。通过事先算好的 CPU 主频,就能知道时间间隔。
那么,有 2 个问题:
A. calibrate_tsc() 是用于计算主频继而确定时间的,那么它如何确定 5ms 或者其它时间?
B. CPU 的实际主频有可能发生变化,例如某些笔记本在未接通电源时,自动将主频减半以节电,那时间是否会变得不精确?
为了回答问题 A,就必须介绍 PIT:
4. 可编程间隔定时器(Programmable Interval Timer, PIT)
PIT 永远以内核确定的固定频率不停的发出中断。每个 IBM 兼容 PC 都至少包含一个 PIT,PIT 通常是使用 0x40~0x43 I/O 端口的一个 8254 CMOS 芯片。
为了回答问题 B,就必须介绍下面的几个定时器:
5. CPU 本地定时器
一种能够产生单步中断或周期性中断的设备,类似 PIT。
6. 高精度事件定时器(High Precision Event Timer, HPET)
其时钟信号的频率至少为 10MHz,即计数器最少可以每 100ns 增加 1 次。
7. ACPI 电源管理定时器(Advanced Configuration and Power Interface Power Management Timer, ACPI PMT)
该设备其实是一个计数器,其时钟信号固定为 3.58MHz,在每个时钟节拍到来时增加 1。
如果操作系统或者 BIOS 可以通过动态降低 CPU 的工作频率或者工作电压来节省电池的电能,那么 ACPI 电源管理定时器就比 TSC 更优越。在这种情况下,TSC 的频率发生改变,这会导致时间偏差及其它的不良后果,但 ACPI PMT 的频率不会改变。