时间在内核中占有重要地位,操作系统必须随时都能获得当前时间,其次操作系统必须提供一种计时器可以通知内核某一段时间已经过去了。时间在内核中最常见的应用就是进程调度,内核不但要为每个进程分配时间片,而且要周期性的对可运行队列中的进程进行调整。Linux内核中的时间由两种设备同时进行计时:实时时钟和系统定时器。
实时时钟
实时时钟(Real Time Clock)用来永久存放系统时间,即便系统关闭也可以靠主板上的电池继续进行计时。由于RTC通常和CMOS被集成在一起,因此RTC也称为CMOS时钟。虽然可以通过操作/dev/rtc对RTC进行编程,但是一般Linux只用RTC来获取当前的时间和日期。当系统启动时,内核通过读取RTC来初始化墙上时间,该时间存放在xtime变量中。所谓墙上时间也就是当前的实际时间。
系统定时器
系统定时器是内核时间机制中最重要的一部分,它提供了一种周期性触发中断机制,即系统定时器以HZ(时钟节拍率)为频率自行触发时钟中断。当时钟中断发生时,内核就通过时钟中断处理程序timer_interrupt()对其进行处理。
系统定时器完全由操作系统管理,因此也成为系统时钟或者软件时钟。当系统启动时,内核通过RTC初始化系统定时器,系统定时器接着由操作系统共掌管,进行固定频率的定时。可以看到,系统时间并不是传统意义上的那种计时时钟,而是通过定时这种特殊的方式来表现时间。在x86架构下,系统时钟通过可编程间隔定时器(PIT)这种设备产生定时。
内核定时器
内核定时器也称为动态定时器,它可以使任务能在指定的时间点上执行。要使用定时器,必须先设置好定时器超时的时间,指定超时发生后应该执行的内核函数,最后激活这个定时器实例。当定时器超时的时候,该内核函数将被自动执行(但不周期执行),执行完毕后自行销毁,这也是内核定时器被称为动态定时器的原因。
获得时间
内核通过xtime变量保存墙上时间,该变量是timespec类型的,在linux/time.h中定义如下:
struct timespec { __kernel_time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
其中,tv_sec是以秒为单位时间,它保存着从1970年7月1日以来经过的时间,而tv_nsec记录自上一秒开始经过的纳秒数。
在最新的内核中,xtime未导出因此不能在内核模块中使用。不过内核提供了内核函数current_kernel_time()来获取当前时间,该函数返回timespec类型的时间。