内核:2.6.24
平台:x86 32位
在 linux 中有一个脉搏,它就是 HZ,在现代的 X86 上,改值被定义为 1000 ,也就是说每 1ms 会产生一次时钟中断,这个时钟间隔叫做一个节拍 (tick) 。
TICK_NSEC 就是以纳秒为单位来表示这个节拍的长度。TICK_NSEC 被定义为:
[C++] 纯文本查看 复制代码 /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */
#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))
上面, ACTHZ 表示实际的 HZ,这个值在这里并不是 1000,而是经过扩展为 256 倍后的一个中间值。之所以扩展,正是为了提高其精度,它的定义为:
[C++] 纯文本查看 复制代码 /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))
上面的两个宏都用到共同的一个宏 SH_DIV 。该宏目的是提高整数除法的精度,它定义为:
[C++] 纯文本查看 复制代码 /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can
* improve accuracy by shifting LSH bits, hence calculating:
* (NOM << LSH) / DEN
* This however means trouble for large NOM, because (NOM << LSH) may no
* longer fit in 32 bits. The following way of calculating this gives us
* some slack, under the following conditions:
* - (NOM / DEN) fits in (32 - LSH) bits.
* - (NOM % DEN) fits in (32 - LSH) bits.
*/
#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \
+ ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
关于 SH_DIV 的探讨可参考:http://www.groad.net/bbs/read.php?tid-3328.html
最后算得 TICK_NSEC 的值为 999848ns (产生的时钟信号频率大约为 1000.15Hz)。 |