Linux定时器与时钟源与jiffies
一、jiffies
它给内核提供节拍,内核中使用jiffies来管理。比如调度、性能统计等,都是以jiffies为单位来实现的。 这些调度和内核活动不能考硬件定时器来管理,否则定时器得忙死。
jiffies本身是定时器实现的,其他的内核获取时间或是其他的度量读取它就行,这就省了很多事。 因为以前它是32位实现的,所以可能会出现回转。 所以jiffies不能直接比较(64位的时候是可以直接比较的,但内核代码还是得照顾到32位,所以出现了一些比较的宏)。
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(b) - (long)(a) < 0))
a是否在b之后;a是否大于b
解决方法:
它在比较的时候只是简单的把unsigned long变成long,最高bit变为符号位。 那么如果超时,jiffies回转了,那么它会从一个负数大值变成一个小的正值; 比较的变量会变成一个负数的大值。
如果没有回转,他们可能都是负数,也可能都是正数。他们是负数的时候,显然a负的更少,所以相减小于0(负数是补码);如果他们是正数,那么b大于a
二、定时器与时钟源
linux内核完成两种定时测量需求:
1. 当前的时间和日期,叫墙上时间
2. 维持定时器,告诉用户某一时间间隔已经过去了。(它能通知用户。定时器不可能通过内核自己获取两个时间,然后相减这样实现,因为不可能让系统不停的去获取时间,这样它就干不了别的事儿了)
根据上面两种需求就有了两种硬件:
时钟源:它是一种像钟一样的硬件,不停的以固定间隔滴答(比如接口time(),ftime(),gettimeofday()来获取当前的时间)
定时器:定时器硬件可以编程设置间隔时间的设备,并且在超时以后会发中断信号(settimer()和alarm())
那么为什么不使用时钟源来做定时器呢?或是说是否可以改造时钟源来作为定时器呢?
实际上是可以的! RTC就是这样的一种设备,但是RTC精度太差。
然而问题来了,为什么不用TSC时钟源作为定时设备呢?
TSC实际上是每个时钟周期去改一下寄存器的值,可以通过RDTSC读取。 我们是否可以依次实现一个软件的定时器呢?
这不太可行,因为他只是个累加器,不知道什么时候发信号,如果你要让它发信号的话,必须跑一个小程序不停的读取时间,比较是否超时,那么太耗cpu了
因此!!! 我们需要一个硬件的定时器,不需要CPU管的家伙!
但是这么说,那么TSC还有什么鸟用? 而且我们是否可以通过改造TSC电路来硬件触发定时器信号呢?
其实目前使用的APIC跟TSC类似,它也是基于CPU时钟信号的。比如每隔1,2,4,8,16,32,64或128个时钟信号就对定时器进行递减。所以它的精度极高。
另外HPET也是一种定时器,同时亦是时钟源