Contents

Linux内核必须完成的两种主要定时测量:

保存当前的时间和日期,以便通过time()、ftime()、gettimeofday()系统调用把它们返回给用户程序,也可以由内核本身把当前时间作为文件和网络包的时间戳。

维持定时器,这种机制能够告诉内核或用户程序某一时间间隔已经过去了。

一般会遇到的几种时钟和定时器电路:实时时钟(Real Time Clock RTC)、时间戳计数器(Time Stamp Counter TSC)、可编程间隔定时器(Programmable Interval Timer PIT)、CPU本地定时器(APIC中)、高精度事件定时器(HPET)、ACPI电源管理定时器。

Linux的计时体系结构是一组与时间流相关的内核数据结构和函数。实际上,基于80x86多处理器机器所具有的计时体系结构与单处理器机器所具有的稍有不同:

在三处理器系统上,所有的计时活动都是由全局定时器(可以是可编程间隔定时器也可以是高精度事件定时器)产生的中断触发的。

在多处理器系统上,所有普通的活动(像软定时器处理)都是由全局定时器产生的中断触发的,而具体的CPU的活动(像监控当前运行进程的执行时间)是由本地APIC定时器产生的中断触发的。

jiffies

jiffies是一个计数器,用来记录自系统启动依赖产生的节拍总数。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。因为一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就为Hz。系统运行时间以秒为单位计算,就等于jiffies/Hz。

xtime

xtime变量存放当前时间和日期;它是一个timespec类型的数据结构,该结构有两个字段:

1.tv_sec 存放自1970年1月1日(UTC)午夜以来经过的秒数。

2.tv_nsec存放自上一秒开始经过的纳秒数(它的值域范围在0-999999999之间)

在单处理器系统上,所有与定时有关的活动都是由IRQ线0上的可编程间隔定时器产生的中断触发的。

多处理器系统可以依赖两种不同的时钟中断源:可编程间隔定时器或高精度事件定时器产生的中断,以及CPU本地定时器产生的中断(监管内核代码并检测当前进程在特定CPU上已经运行了多长时间)。

内核在于定时相关的其他任务中必须周期性地收集若干数据用于:

检查运行进程的CPU资源限制  

更新与本地CPU工作负载有关的统计数  

计算平均系统负载  

监管内核代码  

软定时器和延迟函数

定时器是一种软件功能,即允许在将来的某个时期,函数在给定的时间间隔用完时被调用。超时(time-out)表示与定时器相关的时间间隔已经用完的那个时刻。

Linux考虑两种类型的定时器,即动态定时器(dynamic timer)和间隔定时器(interval timer)。第一种类型由内核使用,而间隔定时器可以由进程在用户态创建。

延迟函数

当内核需要等待一个较短的时间间隔(比方说,不超过几毫秒)时,就不需要使用软定时器。

开发驱动,需要较短的时间间隔,在以上情况下,内核使用udelay()和ndelay()函数:前者接收一个微妙级的时间间隔作为它的参数,并在指定的延迟结束后返回;后者与前者类似,但是指定的延迟参数是纳秒级的。

本文章参考自《深入理解linux内核》。

Contents