linux 时钟管理,Linux 时钟管理

hrtimer 首先要实现的功能就是要克服 timer wheel 的缺点:低精度以及与内核其他模块的高耦合性。在正式介绍 hrtimer 之前,有必要先介绍几个常用的基本概念:

时钟源设备(clock-source device)

系统中可以提供一定精度的计时设备都可以作为时钟源设备。如 TSC,HPET,ACPI PM-Timer,PIT 等。但是不同的时钟源提供的时钟精度是不一样的。像 TSC,HPET 等时钟源既支持高精度模式(high-resolution mode)也支持低精度模式(low-resolution mode),而 PIT 只能支持低精度模式。此外,时钟源的计时都是单调递增的(monotonically),如果时钟源的计时出现翻转(即返回到 0 值),很容易造成计时错误, 内核的一个 patch(commit id: ff69f2)就是处理这类问题的一个很好示例。时钟源作为系统时钟的提供者,在可靠并且可用的前提下精度越高越好。在 Linux 中不同的时钟源有不同的 rating,具有更高 rating 的时钟源会优先被系统使用。如图 2 所示:

表 1. 时钟源中 rating 的定义

1 ~ 99

100 ~ 199

200 ~ 299

300 ~ 399

400 ~ 499

非常差的时钟源,只能作为最后的选择。如 jiffies

基本可以使用但并非理想的时钟源。如 PIT

正确可用的时钟源。如 ACPI PM Timer,HPET

快速并且精确的时钟源。如 TSC

理想时钟源。如 kvm_clock,xen_clock

时钟事件设备(clock-event device)

系统中可以触发 one-shot(单次)或者周期性中断的设备都可以作为时钟事件设备。如 HPET,CPU Local APIC Timer 等。HPET 比较特别,它既可以做时钟源设备也可以做时钟事件设备。时钟事件设备的类型分为全局和 per-CPU 两种类型。全局的时钟事件设备虽然附属于某一个特定的 CPU 上,但是完成的是系统相关的工作,例如完成系统的 tick 更新;per-CPU 的时钟事件设备主要完成 Local CPU 上的一些功能,例如对在当前 CPU 上运行进程的时间统计,profile,设置 Local CPU 上的下一次事件中断等。和时钟源设备的实现类似,时钟事件设备也通过 rating 来区分优先级关系。

tick device

Tick device 用来处理周期性的 tick event。Tick device 其实是时钟事件设备的一个 wrapper,因此 tick device 也有 one-shot 和周期性这两种中断触发模式。每注册一个时钟事件设备,这个设备会自动被注册为一个 tick device。全局的 tick device 用来更新诸如 jiffies 这样的全局信息,per-CPU 的 tick device 则用来更新每个 CPU 相关的特定信息。

broadcast

CPU 的 C-STATECPU 在空闲时会根据空闲时间的长短选择进入不同的睡眠级别,称为 C-STATE。C0 为正常运行状态,C1 到 C7 为睡眠状态,数值越大,睡眠程度越深,也就越省电。CPU 空闲越久,进入睡眠的级别越高,但是唤醒所需的时间也越长。唤醒也是需要消耗能源的,因此,只有选择合适的睡眠级别才能确保节能的最大化。

Broadcast 的出现是为了应对这样一种情况:假定 CPU 使用 Local APIC Timer 作为 per-CPU 的 tick device,但是某些特定的 CPU(如 Intel 的 Westmere 之前的 CPU)在进入 C3+ 的状态时 Local APIC Timer 也会同时停止工作,进入睡眠状态。在这种情形下 broadcast 可以替代 Local APIC Timer 继续完成统计进程的执行时间等有关操作。本质上 broadcast 是发送一个 IPI(Inter-processor interrupt)中断给其他所有的 CPU,当目标 CPU 收到这个 IPI 中断后就会调用原先 Local APIC Timer 正常工作时的中断处理函数,从而实现了同样的功能。目前主要在 x86 以及 MIPS 下会用到 broadcast 功能。

Timekeeping & GTOD (Generic Time-of-Day)

Timekeeping(可以理解为时间测量或者计时)是内核时间管理的一个核心组成部分。没有 Timekeeping,就无法更新系统时间,维持系统“心跳”。GTOD 是一个通用的框架,用来实现诸如设置系统时间 gettimeofday 或者修改系统时间 settimeofday 等工作。为了实现以上功能,Linux 实现了多种与时间相关但用于不同目的的数据结构。

struct timespec {

__kernel_time_t tv_sec; /* seconds */

long tv_nsec; /* nanoseconds */

};

timespec 精度是纳秒。它用来保存从 00:00:00 GMT, 1 January 1970 开始经过的时间。内核使用全局变量 xtime 来记录这一信息,这就是通常所说的“Wall Time”或者“Real Time”。与此对应的是“System Time”。System Time 是一个单调递增的时间,每次系统启动时从 0 开始计时。

struct timeval {

__kernel_time_t tv_sec; /* seconds */

__kernel_SUSEconds_t tv_usec; /* microseconds */

};

timeval 精度是微秒。timeval 主要用来指定一段时间间隔。

union ktime {

s64 tv64;

#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)

struct {

# ifdef __BIG_ENDIAN

s32 sec, nsec;

# else

s32 nsec, sec;

# endif

} tv;

#endif

};0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值