Contents

Linux内核-定时器篇

计算机中的许多活动都是由定时器来进行驱动的,如:每5ms一次的时钟中断、系统时间的更新、软定时器、进行调度中的时间片控制等等。

LInux内核中的内核定时功能主要分为两种:

1、维持系统时间,共time()、gettimeofday()等系统调用和内核使用。

2、维持一个定时器,以便通知内核某一时间间隔已经过去。

硬件定时系统

时钟和定时器的实现依赖于硬件的定时器电路,主要有以下几种:

1、RTC (Real Time Clock)时钟

存在于主板上,独立于CPU和其他电路,由单独的供电器。

RTC会在IRQ8上发出周期性的中断。

Linux只使用RTC获取时间和日期,可以通过对/dev/rtc进行操作,来对RTC进行编程。

2、TSC (Time Stamp Counter)TSC 时间戳计数器

TSC 包含在处理器内部,有一条clk的输入引脚,来记录外部时钟振荡器的周期数,在每个时钟信号到来时+1。

TSC 的值保存在寄存器中,通过汇编 rdtsc 可以获取寄存器的值。

TSC 的增加次数和 CPU频率有关,如果是1GHZ,那么每ns增加一次。

时钟信号的频率由Linux在初始化系统的时候进行确定。

3、PIT (Programmable Interval Timer)可编程间隔定时器

PIT 的作用类似于闹钟,存在于CPU内部,可在一个时间间隔以后发出时钟中断,用来产生系统的时钟中断

PIT 的时间间隔是固定的,如 1ms。

4、CPU 本地定时器

在 CPU 的本地 APIC 中,还有一种定时测量设备。

CPU 本地定时器 和 PIT 有些区别:

  • APIC计数器是32位,PIC是64位,这意味着PIT可以产生频率更低的中断(计数器中存放的是节拍数)。
  • APIC的时钟信号基于总线,PIT内部有自己的时钟振荡器。
  • APIC只把终端发给自己的CPU,而PIT产生全局性中断(这点在SMP系统中是有区别的)。

5、HPET 高精度事件定时器

Intel和Microsoft开发的新型定时芯片,使用不普遍。

包含8个计数器,每个计数器有自己的时钟信号驱动,是功能更强的硬件定时器。

UP 的计时体系结构

在单处理器系统上,所有与定时有关的活动都由PIT产生的中断触发。

SMP 的计时体系结构

在多处理器系统中,时钟中断源有两种:

  • CPU本地定时器的中断,APIC
  • 可编程定时器中断,PIT或HPET

PIT或HPET产生的时钟中断称为 全局时钟中断,负责不涉及具体CPU的活动,如:软定时器和系统时间的更新。

APIC产生的本地时钟中断触发涉及本地 CPU的活动:如监视进程的运行时间。

软定时器和延迟函数

定时器是一种软件功能,在未来的某个时刻进行函数的调用。

定时器的实现思路很简单,相关的数据结构中包含一个时刻,在时钟中断到来时,比较时刻 与 当前时刻 jiffies 的大小即可判断定时器是否到达时间。

动态定时器-多级时间轮

https://hugo-github-io.oss-cn-beijing.aliyuncs.com/img/202307251003698.png

动态定时器的实现使用了多级时间轮的数据结构,不详细描述。

对软定时器的处理比较耗时,因此不在时钟中断处理例程中进行处理,而是被延迟到软中断中进行执行,这里是 TIMER_SOFTIRQ。

由于定时器的执行由 softirq 执行,其精度会有一定的影响,执行可能会被延迟几百毫秒。

延迟函数

当内核需要等待一个较短的时间间隔(几毫秒)时使用。

执行指令循环到目标时间。

相关系统调用

time() 和 gettimeofday()

time() 获取从1970.1.1以来的秒数

gettimeofday() 获取从1970.1.1以来的秒数 + 纳秒数

setitimer() 和 alarm()

omit.

Reference

[1] 深入理解LINUX内核