1 / 33

Linux 中的时钟

Linux 中的时钟. xlanchen@2006.6.15. 定时测量. Linux 内核提供两种主要的定时测量 获得当前的时间和日期 系统调用: time(), ftime() 以及 gettimeofday() 维持定时器 settimer(), alarm() 定时测量是由基于固定频率振荡器和计数器的几个硬件电路完成的. 主要内容. 定时的硬件设备 Linux 内核中与时间有关的程序 系统调用及相关服务例程. 硬时钟. 80x86 体系结构上,内核必须显式的与四种时钟打交道 实时时钟 Real time clock , RTC

clem
Télécharger la présentation

Linux 中的时钟

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Linux中的时钟 xlanchen@2006.6.15

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  22. 更新xtime Embedded Operating Systems

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

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

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

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

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

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

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

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

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

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

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

More Related