今天,再次碰到一个由于系统时间调整导致的bug。不得不再次查找完美的问题解决方案。
虽然,按道理来说,系统时间进行重置之后,一些应用程序的行为出现异常是合乎情理,并且是可以被理解并接受的,最重要的是这样的问题都可以通过重新启动操作系统来解决(微软大哥解决问题之道),但是,对于软件开发人员来说,应该尽量避免非必要的重启。对自己严格要求点儿似乎没什么过错!?
对绝对时间的依赖似乎不怎么容易摆脱,但是我们的应用程序又有多少是严格依赖于系统的绝对时间呢?很多时候,我们只要求能够求出时间间隔就可以了。时间间隔实际上是可以抛开绝对时间求得的,我们可以采用相对于某个时间点的相对时钟来计时,比如说系统启动时间。
自然地,我们就想到了proc伪文件系统下的/proc/uptime文件。通过读这个文件,我们能够获得相对于系统启动时刻的相对时间,其精度为百分之一秒:
[xiaosuo@Ulard-iolo ~]$ cat /proc/uptime 4057840.13 3326432.09
|
读/proc/uptime简单易行,也适合shell操作,但是只为了一个简单的相对时间就进行三次系统调用(open, read, close)和一次字符串解析,这样的复杂度显然不能满足吹毛求疵的我这种人的非礼要求。
联想到Linux内核空间的精度为(1/HZ)秒的计时变量jiffies,如果有哪个系统调用把它导到用户空间,其效率可见是比较高的,再次扒到了系统调用times:
#include <sys/times.h>
clock_t times(struct tms *buf);
|
times的返回值是相对于某个固定时刻的时间。这个固定时刻,在2.4内核及其之前是系统启动,以后就改成了系统启动((2^32/HZ) - 300)秒之前(这个对jiffies初始值的改动是为了使Linux内核能够尽快地暴露有关jiffies变量回卷的bug)。所以,应用程序不要依赖于这个开始时刻,如果非要依赖,可以通过其他的方式先得到系统的启动时间,然后与其做差值,求得偏移量,以后就能参考这个偏差求得系统的启动时间。这个函数的返回值clock_t的单位为(1/sysconf(_SC_CLK_TCK);)秒(sysconf(_SC_CLK_TCK)通常为100),并且clock_t可能溢出(在2.6内核的Linux系统上,系统启动5分钟就会溢出),所以需要特别小心。
times虽然高效,但是他的精度还是略显不够,所以我继续挖掘。最终找到了clock_gettime这个系统调用:
#include <time.h>
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
|
clk_id为CLOCK_MONOTONIC的单调时钟能够满足我们的需求,并且它的精度一般都会很高,略微地浏览了一遍它的内核实现,也较为轻量,可谓完美!
以上介绍的三种获得相对时间的方法的详细用法,还请各位在需要的时候去翻看其手册页,具体应用我就不列举了,因为,要洗洗睡了!:)
阅读(3604) | 评论(3) | 转发(0) |