《四Linux内核时钟.ppt》由会员分享,可在线阅读,更多相关《四Linux内核时钟.ppt(25页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、四Linux内核时钟 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望1 1 时钟与定时器时钟与定时器A Linux system actually has two clocks:One is the battery powered Real Time Clock(also known CMOS clock,or Hardware clock)which keeps track of time when the system is turned off but is
2、 not used when the system is running.The other is the system clock(sometimes called the kernel clock or software clock)which is a software counter based on the clock tick.It does not exist when the system is not running,so it has to be initialized from the RTC(or some other time source)at boot time.
3、Linux系统时钟以读取的硬件时钟为起始点,根据系统启动后的滴答数来计算时间,系统内的所有计时均基于它。系统用一个全局变量jiffies表示,该变量每个时钟周期更新一次,即表示系统自启动以来的时钟滴答数目。时钟滴答时钟滴答时钟滴答的长短是由时钟中断的频率决定。譬如每秒有100次时钟中断,那么一个时钟滴答的就是10毫秒(记为10ms),相应地,系统时间就会每10ms增1。不同的操作系统对时钟滴答的设置不同。(DOS为55ms)Linux中用全局变量jiffies表示系统自启动以来的时钟滴答数目。时钟中断的物理产生bottom half-bottom half-任务延迟处理机制任务延迟处理机制硬中
4、断服务程序Top half:必须关中断运行。bottom half:可以打开中断运行。定时器:是系统提供的一种定时服务机制,它能够在某个特定的时刻唤醒某个进程来完成相应的工作。Linux的链表定时器:定时器定时器 next expires data*function()prev next expires data*function()prev next expires data*function()prevexpires=n(s)+当前系统时间 /以jiffies时间为单位进程执行有用户模式和核心模式的区别;进程执行时间也分:用户模式下执行时间和核心模式执行时间。进程可用的定时器分为:ITIM
5、ER_REAL:不管进程在什么模式(甚至被阻塞的时候),它都在计数。SIGALRM信号。ITIMER_VIRTUAL:当进程在用户模式执行时计数。SIGVTALRM信号。ITIMER_PROF:进程在用户模式和核心模式运行时都计数。SIGPROF信号。2.Linux系统时钟的实现系统时钟的实现相关的数据结构及变量:include/linux/xtime.h include/linux/xtime.h struct timeval time_t tv_sec;subseconds_t tv_usec;Tick:时钟中断周期。初值=(1000000+HZ/2)/HZ Xtime:保存系统当前时间的
6、结构体变量。Jiffies:系统启动以来的时钟滴答数。相关的数据结构及变量:wall_jiffies:每次bottom half时用来记 录当前jiffies的变量.TSC:保存CPU的ticks数目.系统时钟初始化:arch/i386/kernel/time.carch/i386/kernel/time.c调用get_cmos_time()函数从cmos中读取硬件时钟赋给tv_sec,初始化 tv_usec 为0。调用setup_irq()重新设置时钟中断irq0的中断服务程序入口。系统时钟的运行:时钟中断发生时,中断服务程序实际上是依靠do_timer()函数来完成其必须完成的工作;do_
7、timer()进一步调用update_times函数来更新系统时间,调用run_timer_list函数来检查、执行定时服务,即在bottom half中完成。系统时钟的设置和调整:系统调用sys_time;/读取,秒级sys_stime;/设置,秒级sys_gettimeofday;/读取,微秒级sys_settimeofday;/设置,微秒级sys_adjtimex;/调整,主要用于网络和分布式系统。时间的准确读取时间的准确读取:最近一次bottom half运行的时间值xtime+从最近一次bottom half到最近一次时钟中断的间隔(jiffies-wall_jiffies)+最近一
8、次时钟中断到当前的时间间隔usec 3.Linux定时器的实现定时器的实现数据结构数据结构:链表节点include/linux/timer.h struct timer_list struct list_head list;unsigned long expires;/定时器的激活时刻 unsigned long data;/函数的参数 void(*function)(unsigned long);/执行函数 链表结构体kernel/timer.c struct timer_vec int index;/定时器链表索引,指向当前要响应的链表。struct list_head vecTVN_SI
9、ZE;/定时器链表数组 ;/TVN_SIZE=64根链表结构体:struct timer_vec_root int index;/定时器链表索引,指向当前要响应的链表。struct list_head vecTVR_SIZE;/定时器链表数组 ;/TVN_SIZE=256定义数组tvecs的5个成员管理定时器链表:static sturct timer_vec tv5;static sturct timer_vec tv4;static sturct timer_vec tv3;static sturct timer_vec tv2;static sturct timer_vec_root t
10、v1;static struct timer_vec*const tvecs=(struct timer_vec *)&tv1,&tv2,&tv3,&tv4,&tv5;IndexVec0IndexVec0VecindexVecindextvecsTimer_listTimer_listTimer_listTimer_listtv3tv4tv5Timer_list型定时器体系结构型定时器体系结构tv1tv2可以采用以下的假定:Tv1 分Tv2 时Tv3 日Tv4 月Tv5 年实现机制实现机制:定时器升序排列,在时钟中断的bottom_half检查当前节点是否到时。实现:实现:由5个定时器数组形成
11、树形链表结构加以实现。-初始化:根据用户空间得到的数据设置初值 并将设定好的定时器挂到链表上。-运行:判断时间到达,由run_timer_list()检查并执行定时服务。run_timer_list()run_timer_list()函数的实现思想:函数的实现思想:1 首先判断tv1.index的值。如果非0,则激活定时器,递增timer_jiffies和tv1.index,使tv1.vectv1.index指向下一个时钟中断服务处理的链表;否则转2。2 tv1.index=0,即tv1为空,调用cascade_timers(tvecs1),从tvecx1(tv2)搬一组链表,分散插入tvec
12、s0(tv1)的各个链表,如果tvecx1为空,则从tvecx2(tv3)搬来一组链表,分散插入tvecx0(tv1),tvecx1(tv2)的各个链表中对于定时器的操作:对于定时器的操作:1 添加add_timer()2 修改先调用detach_timer()将定时器从链表上取下,修改时间后再调用 internal_add_timer()将定时器从新挂接到链表上。3 删除del_timer()4.Linux定时器的应用例定时器的应用例例:例:设置一个ITIMER_REAL类型的定时器,每秒发出一个信号,等到定时到达时,程序统计经过的时间。#include#include#include St
13、atic void sig_handler(int signo);/声明信号量函数声明信号量函数Long lastsec,countsec;/上一秒时间,总的时间花销Int main(void)struct itimerval v;/定时器结构体 long nowsec,nowusec;/当前时间 if(signal(SIGUSR1,sig_handler)=SIG_ERR)printf(“Unable to create handler for SIGUSR1n”);exit(0);if(signal(SIGALRM,sig_handler)=SIG_ERR)printf(“Unable t
14、o create handler for SIGALRMn”);exit(0);v.it_interval.tv_sec=9;v.it_interval.tv_usec=999999;v.it_value.tv_sec=9;v.it_value.tv_usec=999999;/初始化setitimer(ITIMER_REAL,&v,NULL);lastsec=v.it_value.tv_sec;countsec=0;/设置定时器,并挂接到链表上。while(1)getitimer(ITIMER_REAL,&v);nowsec=v.it_value.tv_sec;nowusec=v.it_val
15、ue.tv_usec;if(nowsec=lastsec-1)raise(SIGUSR1);/每过1秒,产生一个信号lastsec=nowsec;countsec+;/信号处理函数,根据不同的信号,输出不同的信息。Static void sig_handler(int signo)switch(signo)case SIGUSER1:printf(“One second passedn”);break;case SIGALRM:printf(“Timer has been zero,elapsed%d secondn”,countsec);lastsec=countsec;countsec=0;break;