Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux 中的时钟 Embedded Operating Systems2 定时测量 Linux 内核提供两种主要的定时测量 获得当前的时间和日期 系统调用: time(), ftime() 以及 gettimeofday() 维持定时器 settimer(),

Similar presentations


Presentation on theme: "Linux 中的时钟 Embedded Operating Systems2 定时测量 Linux 内核提供两种主要的定时测量 获得当前的时间和日期 系统调用: time(), ftime() 以及 gettimeofday() 维持定时器 settimer(),"— Presentation transcript:

1 Linux 中的时钟 xlanchen@2007.6.19

2 Embedded Operating Systems2 定时测量 Linux 内核提供两种主要的定时测量 获得当前的时间和日期 系统调用: time(), ftime() 以及 gettimeofday() 维持定时器 settimer(), alarm() 定时测量是由基于固定频率振荡器和计数器的 几个硬件电路完成的

3 xlanchen@2007.6.19Embedded Operating Systems3 主要内容 定时的硬件设备 Linux 内核中与时间有关的程序 系统调用及相关服务例程

4 xlanchen@2007.6.19Embedded Operating Systems4 硬时钟 80x86 体系结构上,内核必须显式的与四种时 钟打交道 实时时钟 Real time clock , RTC 时间戳计数器 Time stamp counter , TSC 可编程间隔定时器 Programmable interval timer, PIT SMP 系统上的本地 APIC 定时器 用于跟踪 当前时间 用于计时、时钟中断

5 xlanchen@2007.6.19Embedded Operating Systems5 实时时钟 RTC 基本上所有的 PC 都包含实时时钟 独立于 CPU 与所有其他芯片 依靠一个独立的小电池供电 即使关闭 PC 电源,还会继续运转 与 CMOS RAM 往往集成在一个芯片内 例如: Motorala 146818 能在 IRQ8 上发出周期性的中断,频率在 2HZ~8192 之间 可以对其编程实现一个闹钟

6 xlanchen@2007.6.19Embedded Operating Systems6 Linux 只使用 RTC 获得时间和日期 对应的设备文件为 /dev/rtc 可以通过设备文件对其编程 内核通过 0x70 和 0x71 两个端口访问 RTC 系统管理员可以通过执行时钟程序设置时钟

7 xlanchen@2007.6.19Embedded Operating Systems7 时间戳计数器 TSC 这是 80x86 微处理器中的 从 pentium 开始有 64 位的寄存器 rdtsc 指令用于读该寄存器 作为一个计数器,它在每个时钟信号到来时 +1 例如,时钟频率 400MHz 的微处理器, TSC 每 2.5ns+1

8 xlanchen@2007.6.19Embedded Operating Systems8 与后面介绍的可编程间隔定时器相比, TSC 可 以获得更精确的时钟 为此, Linux 在系统初始化的时候必须确定时钟的 频率 calibrate_tsc 根据在一个相对较长的时间间隔内(约 50ms )所发生 的 TSC 计数的个数进行计算 那个间隔由可编程间隔定时器给出 由于只在系统初始化的时候运行一次,因此本程序可以 执行较长时间,而不会引起问题

9 xlanchen@2007.6.19Embedded Operating Systems9 可编程间隔定时器 PIT 经过适当编程后,周期性的给出时钟中断 通常是 8254 CMOS 芯片 使用 I/O 端口 0x40~0x43 Linux 将 PIT 编程为: 100Hz 通过 IRQ0 发出时钟中断 每 10ms 产生一次时钟中断,即一个 tick

10 xlanchen@2007.6.19Embedded Operating Systems10 Linux 在初始化的时候,利用可编程间隔定时 器获得 CPU 的频率 观察 calibrate_tsc() calibrate_tsc

11 xlanchen@2007.6.19Embedded Operating Systems11 Tick 的长短 短 优点:分辨率高 缺点:需要较多的 CPU 时间处理,会导致用户程序 运行变慢 适用于非常强大的机器,这种机器能够承担较大的 系统开销 Tick 的设置是一个折中,例如 在大多数惠普的 Alpha 和 Intel 的 IA-64 上约 1ms 产生 一个 tick (每秒 1024 个时钟中断) Rawhide Alpha 工作站采用更高( 1200tick/ 秒)

12 xlanchen@2007.6.19Embedded Operating Systems12 在 Linux 中,下列宏决定时钟中断频率 每秒钟时钟中断的个数,即每秒 tick 的个数 8254 芯片的内部振荡器频率 对 8254 分频,获得 HZ 所需的时钟

13 xlanchen@2007.6.19Embedded Operating Systems13 在 init_IRQ() 中初始化时钟中断频率 init_IRQ 此后,约每 10ms 就会产生一个 tick

14 xlanchen@2007.6.19Embedded Operating Systems14 Linux 的计时体系结构 在单处理器系统中,所有定时活动都由 IRQ0 上的时钟中断触发,包括 在中断中立即执行的部分,和 作为下半部分延迟执行的部分

15 xlanchen@2007.6.19Embedded Operating Systems15 时钟中断处理例程 Linux 初始化时由 time_init() 建立 IRQ0 对应的中 断处理函数 time_init 将 irq0 作为 irq_desc 的第一项 的中断处理函数

16 xlanchen@2007.6.19Embedded Operating Systems16 如果有 TSC ,那么就得到时钟中断处理延迟, 以给用户提供更精确的时钟 该函数会调用 do_timer 进一步处理

17 xlanchen@2007.6.19Embedded Operating Systems17 do_timer 全局变量,存放自系统启动 以来的时钟节拍数 32 位 约 497 天会溢出(回归为 0 ) 检查当前进程对时间片的使用 情况 激活下半部分 如果 tq_timer 非空,还要激活相关的下半部分处理

18 xlanchen@2007.6.19Embedded Operating Systems18 update_process_times 更新时间片 视需要进行调度 统计当前进程对 CPU 时间的使用 情况

19 xlanchen@2007.6.19Embedded Operating Systems19 TIMER_BH 下半部分 当时钟中断处理例程运行结束并返回时,会立 即处理下半部分 更新系统日期和时间,计算当前的系统负载 维护软定时器处理

20 xlanchen@2007.6.19Embedded Operating Systems20 更新时间和日期 用户程序从下面这个变量中获得当前时间和日 期 存放从 1970 年 1 月 1 日凌晨 0 点 以来经过的所有秒数 最后一秒已经过去的微秒数 取值范围: 0~999999

21 xlanchen@2007.6.19Embedded Operating Systems21 系统初始化时, time_init() 初始化时间和日期 time_init 观察 get_cmos_time() get_cmos_time 获得 coms 时间 一旦完成, Linux 不再需要 RTC , 依靠下半部分维护 xtime

22 xlanchen@2007.6.19Embedded Operating Systems22 更新 xtime

23 xlanchen@2007.6.19Embedded Operating Systems23 软定时器 定时器是一种软件功能,它允许在将来的某个 时刻调用某个函数 大多数设备驱动程序利用定时器完成一些特殊 工作 软盘驱动程序在软盘暂时不被访问时就关闭设备的 发动机 并行打印机利用定时器检测错误的打印机情况

24 xlanchen@2007.6.19Embedded Operating Systems24 Linux 中存在两类定时器: 动态定时器 内核使用 间隔定时器 由进程在用户态创建 注意:由于软定时器在下半部分处理,内核不能保 证定时器正好在时钟到期的时候被执行,会存在延 迟,不适用于实时应用

25 xlanchen@2007.6.19Embedded Operating Systems25 动态定时器 动态定时器被动态的创建和撤销,当前活动的 动态定时器个数没有限制 数据结构: 系统使用 512 个双向链表维护动态定时器 定时器到期时要执行的函数 函数使用的参数 到期时间

26 xlanchen@2007.6.19Embedded Operating Systems26 创建并激活一个动态定时器 创建一个新的 timer_list 对象 调用 init_timer 初始化,并设置定时器要处理的 函数和参数 设置定时时间 使用 add_timer 加入到合适的链表中 通常定时器只能执行一次,如果要周期性的执 行,必须再次将其加入链表

27 xlanchen@2007.6.19Embedded Operating Systems27 动态定时器的处理 为提高处理动态定时器的效率,必须给定时器 排序,并使用合适的数据结构 Linux 根据 expires 的值,维护这样的数据结构

28 xlanchen@2007.6.19Embedded Operating Systems28 =64, 64 个双向链表,包含了未来某个时间段内的 动态定时器 index 指向当前应当用来更新上一级定时器的链表 ( =256 ), 256 个双向链表,每个表示对应 时钟到期时的动态定时器链表 Index 表示当前节拍对应的那个链表 未来 2 14 -1 个节拍内的定时器 每 256 个节拍内的定时器为 1 个链表 共 64 个 未来 2 20 -1 个节拍内的定时器 每 2 14 个节拍内的定时器为 1 个链表 共 64 个 未来 2 26 -1 个节拍内的定时器 每 2 20 个节拍内的定时器为 1 个链表 共 64 个 未来 2 32 -1 个节拍内的定时器 每 2 26 个节拍内的定时器为 1 个链表 共 64 个 一点点不同:最后一个链表中的 定时器的时间可以任意大

29 xlanchen@2007.6.19Embedded Operating Systems29 run_timer_list 下半部分 timer_bh() 调用 run_timer_list() 检查到 期的动态定时器,包括: 执行动态定时器 更新链表 观察 run_timer_list() run_timer_list

30 xlanchen@2007.6.19Embedded Operating Systems30 动态定时器的应用 使用 schedule_timeout() 可以使进程被延迟 (睡眠一段时间) 观察 schedule_timeout() 并看一个内核应用实 例 schedule_timeout

31 xlanchen@2007.6.19Embedded Operating Systems31 与定时测量相关的系统调用 time() 返回从 1970 年 1 月 1 日凌晨 0 点开始的秒数 ftime() 返回从 1970 年 1 月 1 日凌晨 0 点开始的秒数以及最后 一秒的毫秒数 数据结构为 timeb gettimeofday() 返回从 1970 年 1 月 1 日凌晨 0 点开始的秒数 对应于 sys_gettimeofday()

32 xlanchen@2007.6.19Embedded Operating Systems32 settimer() 间隔定时器 频率:周期性的触发定时器(若为 0 ,只触发一次) alarm() 引起 SIGALARM 信号

33 xlanchen@2007.6.19Embedded Operating Systems33 与时钟相关的命令(演示) date :显示或者更改系统时钟 使用 time 获得时钟 使用 ctime 改变时钟格式


Download ppt "Linux 中的时钟 Embedded Operating Systems2 定时测量 Linux 内核提供两种主要的定时测量 获得当前的时间和日期 系统调用: time(), ftime() 以及 gettimeofday() 维持定时器 settimer(),"

Similar presentations


Ads by Google