欢迎访问小站,阅读此文http://www.yandong.org/archives/501
简介
墙上时间,也就是距离1970年1月1日的时间,在linux kernel内部没多大用处,对其的应用多在用户空间。
本文的目的在于在kernel里面计算得到 进程创建的墙上时间
计算公式
xtime.tv_sec-(jiffies/HZ)+300+p->real_start_time.tv_sec
意思就是,当前的墙上时间(xtime) 减去系统启动后的节拍(jiffies)/频率(HZ) 这样得到的是系统启动的墙上时间,即距离1970.1.1的秒数,然后再加上进程结构体中 保存的距离系统启动时间的秒数(p->real_start_time.tv_sec)。
下面分别解释:
task_struct中的时间
p->real_start_time.tv_sec
其中的p是task_struct指针,指向的是进程创建距离系统启动的时间.
task_struct中有两个时间:start_time 和 real_start_time,其中后者包含睡眠时间。
下面是进程创建的部分源码
do_posix_clock_monotonic_gettime(&p->start_time);p->real_start_time=p->start_time;monotonic_to_bootbased(&p->real_start_time);//真实启动时间还须要加上总的睡眠时间
xtime介绍
摘自《深入理解linux内核》
所有的PC都包含一个叫实时时钟(Renl Time Clock RTC)的时钟,它是独立于CPU和所有其他芯片的。
即使当PC呗切断电源,RTC还继续工作,因为它靠一个小电池或蓄电池供电。CMOS RAM和RTC被集成在一个芯片上。
…
Linux只用RTC来获取时间和日期。不过对/dev/rtc设备文件操作,也允许对RTC编程。
内核利用 get_cmos_time函数从实时时钟上读取字1970.1.1(UTC)午夜以来经过的秒数。
xtime_lock顺序所(seqlock)消除了对xtime变量同时访问而可能发生的竞争条件,
对于2.6内核,其定义为(/include/linux/time.h)
externstructtimespec xtime;
对于3.5内核,其定义为(kernel/time/timekeeping.c)
structtimekeeper{...structtimespec xtime;...};staticstructtimekeeper timekeeper;
xtime的获取
因为很难原子的访问结构体中的两个变量,所以kernel并不鼓励直接访问xtime变量,可以使用相关函数
//include/linux/time.hstructtimespec current_kernel_time(void);externvoiddo_gettimeofday(structtimeval*tv);
所以如果在module里面直接使用 xtime,是不行的。但是可以通过硬编码的方式获取
比如:
long*xtime_ptr=&xtime;或者long*xtimr_ptr=0xc0803980
其中的 0xc0803980这个值,是从System.map中获得的,xtime是个全局符号,所有从sytem.map中可以获得它的地址
root@hyd:/home/l# cat /boot/System.map-2.6 | grep xtimec0156230 T update_xtime_cache
c06e3c00 D xtime_lock
c072f654 D inet_peer_gc_maxtime
c0803980 B xtime
c08039a0 b xtime_cache
jiffies介绍
简介
全局变量jiffies用来记录自系统启动以来产生的节拍的总数。
它被用来记录系统自开机以来,已经过了多少tick。每发生一次timer interrupt,Jiffies变数会被加一。
启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。
因为一秒内时钟中断的次数等于Hz,所以jiffes一秒内增加的值也就为Hz,系统运行时间以秒为单位计算,就等于jiffes/Hz。
定义
externu64 __jiffy_data jiffies_64;externunsignedlongvolatile__jiffy_data jiffies;
其中,jiffies_64 和 jiffies 的低32位是重合的,因为32为的jiffies 最多50天就溢出了,而jiffies_64则不用关注溢出问题。
初始化
#define INITIAL_JIFFIES((unsignedlong)(unsignedint)(-300*HZ))jiffies=INITIAL_JIFFIES
可以看出 jiffies 被初始化为5分钟后溢出的一个值,这是为了方便内核调试,以便故障早点出来。
获取
由于jiffies_64 是一个符合变量,不能直接获取,需要下面的使用辅助函数
#if(BITS_PER_LONG<64)u64 get_jiffies_64(void);#elsestaticinline u64 get_jiffies_64(void){return(u64)jiffies;}#endif
当然也可以使用硬编码的方式使用 jiffies
root@hy:/home/#cat/boot/System.map|grep"D jiffies"c06e3b00 D jiffies
c06e3b00 D jiffies_64
从中也可以看到 jiffies 与 jiffies_64的地址是相同的
使用
由于jiffies在五分钟之后,便溢出,所以使用jiffies的原则如下
//如果jiffies变量类型是32位无符号intmax_count=0xffffffffor
max_count=0xffffffffffffffff(64-bit)//如果没有溢出,系统启动后运行的节拍数:jiffies-ITIAL_JIFFIES//系统启动来5分钟的节拍数就是(到jiffies溢出的前一拍):max_count-INITIAL_JIFFIES
在我的代码中,我是这样使用的
unsigendlongjiffies_test=jiffies+HZ;if(time_after(jiffies,jiffies_test)){jiffies=MAX_JIFFIES-jiffies;}else{jiffies=jiffies-INITIAL_JIFFIES;}
其中的 time_after 是内核提供的四个比较函数之一
#definetime_after(a,b)\(typecheck(unsignedlong,a)&&\
typecheck(unsignedlong,b)&&\((long)(b)-(long)(a)<0))#definetime_before(a,b)time_after(b,a)#definetime_after_eq(a,b)\(typecheck(unsignedlong,a)&&\
typecheck(unsignedlong,b)&&\((long)(a)-(long)(b)>=0))#definetime_before_eq(a,b)time_after_eq(b,a)
为什么time_after能判断溢出呢?
待续,或者 参考下面链接
链接
http://book.51cto.com/art/200810/93773.htm
http://blog.csdn.net/michaelcao1980/article/details/7826326
http://lxr.oss.org.cn/source/include/linux/jiffies.h?v=2.6.30#L167
http://blog.csdn.net/chchchdx123/article/details/6270022
http://linux.gongxiang8.com/456430/
如果您喜欢这篇文章,欢迎分享订阅。本文内容遵CC版权协议 转载请注明出处www.yandong.org