《Linux中的时钟和定时测量.ppt》由会员分享,可在线阅读,更多相关《Linux中的时钟和定时测量.ppt(36页珍藏版)》请在三一办公上搜索。
1、Linux操作系统分析,中国科学技术大学计算机系陈香兰(051287161312)助教:裴建国、冯晓静Autumn 2008,Linux中的时钟和定时测量,中国科学技术大学计算机系陈香兰(051287161312)助教:裴建国、冯晓静Autumn 2008,2023/11/8,Linux OS Analysis,3/36,定时测量,Linux内核提供两种主要的定时测量获得当前的时间和日期系统调用:time(),ftime()以及gettimeofday()维持定时器settimer(),alarm()定时测量是由基于固定频率振荡器和计数器的几个硬件电路完成的,2023/11/8,Linux O
2、S Analysis,4/36,主要内容,定时的硬件设备Linux内核中与时间有关的程序实现CPU分时、更新系统时间、维护软定时器与定时测量相关的系统调用及相关服务例程,2023/11/8,Linux OS Analysis,5/36,硬时钟,80 x86体系结构上,内核必须显式的与四种时钟打交道实时时钟Real time clock,RTC时间戳计数器Time stamp counter,TSC可编程间隔定时器Programmable interval timer,PITSMP系统上的本地APIC定时器,用于跟踪当前时间,产生周期性的时钟中断,用于计时,2023/11/8,Linux OS
3、Analysis,6/36,实时时钟RTC,基本上所有的PC都包含实时时钟独立于CPU与所有其他芯片依靠一个独立的小电池供电给RTC中的振荡器即使关闭PC电源,还会继续运转与CMOS RAM往往集成在一个芯片内例如:Motorala 146818能在IRQ8上发出周期性的中断,频率在2HZ8192之间可以对其编程实现一个闹钟,2023/11/8,Linux OS Analysis,7/36,Linux本身只使用RTC获得时间和日期对应的设备文件为/dev/rtc可以通过设备文件对其编程内核通过0 x70和0 x71两个端口访问RTC系统管理员可以通过执行时钟程序设置时钟,2023/11/8,L
4、inux OS Analysis,8/36,时间戳计数器TSC,在80 x86微处理器中,有一个CLK输入引线接收外部振荡器的时钟信号从pentium开始,很多80 x86微处理器都引入了一个TSC一个64位的、用作时间戳计数器的寄存器它在每个时钟信号(CLK)到来时+1例如时钟频率400MHz的微处理器,TSC每2.5ns就+1rdtsc指令用于读该寄存器,2023/11/8,Linux OS Analysis,9/36,与后面介绍的可编程间隔定时器相比,TSC可以获得更精确的时钟为此,Linux在系统初始化的时候必须确定时钟信号CLK的频率(即CPU的实际频率)calibrate_tsc根
5、据在一个相对较长的时间间隔内(约50ms)所发生的TSC计数的个数进行计算那个间隔由可编程间隔定时器给出由于只在系统初始化的时候运行一次,因此本程序可以执行较长时间,而不会引起问题,2023/11/8,Linux OS Analysis,10/36,可编程间隔定时器PIT,经过适当编程后,可以周期性的给出时钟中断通常是8254 CMOS芯片使用I/O端口0 x400 x43Linux将PIT编程为:100Hz通过IRQ0发出时钟中断每10ms产生一次时钟中断,即一个tick,2023/11/8,Linux OS Analysis,11/36,Tick的长短,短优点:分辨率高缺点:需要较多的CP
6、U时间处理,会导致用户程序运行变慢适用于非常强大的机器,这种机器能够承担较大的系统开销Tick的设置是一个折中,例如在大多数惠普的Alpha和Intel的IA-64上约1ms产生一个tick(每秒1024个时钟中断)Rawhide Alpha工作站采用更高(1200tick/秒),2023/11/8,Linux OS Analysis,12/36,在Linux中,下列宏决定时钟中断频率,每秒钟时钟中断的个数,即每秒tick的个数,8254芯片的内部振荡器频率,每秒多少次,对8254分频,获得HZ所需的时钟,2023/11/8,Linux OS Analysis,13/36,在init_IRQ(
7、)中初始化时钟中断频率,此后,只要允许处理时钟中断,约每10ms就会产生一个时钟中断1tick约为10ms,2023/11/8,Linux OS Analysis,14/36,如何计算CPU的时钟频率CLK,Linux在初始化的时候,利用可编程间隔定时器获得CPU的频率观察calibrate_tsc(),了解如何计算CPU的频率已知:PIT的频率未知:CLK频率方法:统计在PIT已知的一段时间内(50ms),CLK发生了多少次;然后计算出CLK频率(次数/50ms),2023/11/8,Linux OS Analysis,15/36,Linux的计时体系结构,Linux要周期性的执行一些任务,
8、例如更新系统自启动以来所经过的时间更新时间和日期确定进程运行了多久检查每个软定时器是否已经到期,2023/11/8,Linux OS Analysis,16/36,在单处理器系统中,所有定时活动都由IRQ0上的时钟中断触发,包括在中断中立即执行的部分,和作为下半部分延迟执行的部分,2023/11/8,Linux OS Analysis,17/36,PIT的时钟中断处理例程,Linux初始化时由time_init()建立IRQ0对应的中断处理函数,将irq0作为irq_desc的第一项的中断处理函数,2023/11/8,Linux OS Analysis,18/36,如果有TSC,那么就得到时钟
9、中断处理延迟,以给用户提供更精确的时钟,该函数会调用do_timer进一步处理,2023/11/8,Linux OS Analysis,19/36,do_timer,全局变量,存放自系统启动以来的时钟节拍数32位约497天会溢出(回归为0),检查当前进程对时间片的使用情况,激活下半部分,如果tq_timer非空,还要激活相关的下半部分处理,2023/11/8,Linux OS Analysis,20/36,update_process_times,更新时间片视需要进行调度,统计当前进程对CPU时间的使用情况,2023/11/8,Linux OS Analysis,21/36,TIMER_BH下
10、半部分,当时钟中断处理例程运行结束并返回时,会立即处理下半部分,更新系统日期和时间,计算当前的系统负载,维护软定时器处理,2023/11/8,Linux OS Analysis,22/36,更新时间和日期,用户程序从下面这个变量中获得当前时间和日期,存放从1970年1月1日凌晨0点以来经过的所有秒数,最后一秒已经过去的微秒数取值范围:0999999,2023/11/8,Linux OS Analysis,23/36,系统初始化时,time_init()初始化时间和日期观察get_cmos_time(),获得coms时间一旦完成,Linux不再需要RTC,依靠下半部分维护xtime,2023/1
11、1/8,Linux OS Analysis,24/36,更新xtime,上一次xtime更新后的jiffies,2023/11/8,Linux OS Analysis,25/36,软定时器,定时器是一种软件功能,它允许在将来的某个时刻调用某个函数大多数设备驱动程序利用定时器完成一些特殊工作软盘驱动程序在软盘暂时不被访问时就关闭设备的发动机并行打印机利用定时器检测错误的打印机情况,2023/11/8,Linux OS Analysis,26/36,Linux中存在两类定时器:动态定时器内核使用间隔定时器由进程在用户态创建注意:由于软定时器在下半部分处理,内核不能保证定时器正好在时钟到期的时候被执
12、行,会存在延迟,不适用于实时应用,2023/11/8,Linux OS Analysis,27/36,动态定时器,动态定时器被动态的创建和撤销,当前活动的动态定时器个数没有限制数据结构:系统使用512个双向链表维护动态定时器,定时器到期时要执行的函数,函数使用的参数,到期时间,2023/11/8,Linux OS Analysis,28/36,创建并激活一个动态定时器,创建一个新的timer_list对象调用init_timer初始化,并设置定时器要处理的函数和参数设置定时时间使用add_timer加入到合适的链表中通常定时器只能执行一次,如果要周期性的执行,必须再次将其加入链表,2023/1
13、1/8,Linux OS Analysis,29/36,动态定时器的处理,为提高处理动态定时器的效率,必须给定时器排序,并使用合适的数据结构Linux根据expires的值,维护这样的数据结构,2023/11/8,Linux OS Analysis,30/36,=64,64个双向链表,包含了未来某个时间段内的动态定时器index指向当前应当用来更新上一级定时器的链表,(=256),256个双向链表,每个表示对应时钟到期时的动态定时器链表Index表示当前节拍对应的那个链表,未来214-1个节拍内的定时器每256个节拍内的定时器为1个链表共64个,未来220-1个节拍内的定时器每214个节拍内的
14、定时器为1个链表共64个,未来226-1个节拍内的定时器每220个节拍内的定时器为1个链表共64个,未来232-1个节拍内的定时器每226个节拍内的定时器为1个链表共64个,一点点不同:最后一个链表中的定时器的时间可以任意大,2023/11/8,Linux OS Analysis,31/36,run_timer_list,下半部分timer_bh()调用run_timer_list()检查到期的动态定时器,包括:执行动态定时器更新链表观察run_timer_list(),2023/11/8,Linux OS Analysis,32/36,动态定时器的应用,使用schedule_timeout(
15、)可以使进程被延迟(睡眠一段时间)观察schedule_timeout()并看一个内核应用实例,2023/11/8,Linux OS Analysis,33/36,与定时测量相关的系统调用,time()返回从1970年1月1日凌晨0点开始的秒数ftime()返回从1970年1月1日凌晨0点开始的秒数以及最后一秒的毫秒数数据结构为timebgettimeofday()返回从1970年1月1日凌晨0点开始的秒数对应于sys_gettimeofday(),2023/11/8,Linux OS Analysis,34/36,settimer()间隔定时器频率:周期性的触发定时器(若为0,只触发一次)alarm()引起SIGALARM信号,2023/11/8,Linux OS Analysis,35/36,与时钟相关的命令,date:显示或者更改系统时钟使用time获得时钟使用ctime改变时钟格式,2023/11/8,Linux OS Analysis,36/36,Project 5,具体要求参见课程主页分析下列几个内核函数calibrate_tsc、get_cmos_time、run_timer_list、schedule_timeout在用户态编写一个程序,该程序设定一个定时器,在时间到期的时候做出某种可观察的响应方法不限分析你的程序的实际执行借助了内核的哪些机制,