欢迎转载,转载请注明出处:http://forever.blog.chinaunix.net

一、编写linux下应用程序的时候,有时候会用到高精度相对时间的概念,比如间隔100ms。那么应该使用哪个时间函数更准确呢?

1、time

该函数返回的是自1970年以来的秒数,显然精度不够,不能使用

2、gettimeofday

该函数返回的是自1970年以来的秒数和微秒数,精度显然是够了。我想有很多程序员也是用的这个函数来计算相对时间的,如果说系统时间因为ntp等原因发生时间跳变,那么用这个函数来计算相对时间是不是就会出问题了。所以说这个函数也不能使用

3、clock_gettime

该函数提供了4种类型CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_PROCESS_CPUTIMEID、CLOCK_THREAD_CPUTIME_ID。从字面意思可以判断出来,CLOCK_MONOTONIC提供了单调递增的时间戳,该函数返回值为自系统启动后秒数和纳秒数,但是该函数没有考虑ntp的情况,所以并不是绝对意义上的单调递增(见二)。CLOCK_REALTIME is affected by settime()/settimeofday() calls and can also be frequency corrected by NTP via adjtimex().

CLOCK_MONOTONIC is not affected by settime()/settimeofday(), but is frequency adjusted by NTP via adjtimex().With Linux,NTP normally uses settimeofday() for large corrections (over half a second). The adjtimex() inteface allows for small clock frequency changes (slewing). This can be done in a few different ways, see the man page for adjtimex.CLOCK_MONOTONIC_RAW that will not be modified at all, and will have a linear correlation with the hardware counters.

4、syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &monotonic_time)

该函数提供了真正意义上的单调递增时间(见三)

二、glibc 中clock_gettime(CLOCK_MONOTONIC)的原理

查看glibc的代码可以看到这个数值是由内核计算的。

__vdso_clock_gettime-------->do_monotonic

这个函数的实现如下:

点击(此处)折叠或打开

notrace static noinlineintdo_monotonic(struct timespec*ts)

{

unsigned long seq,ns,secs;

do {

seq=read_seqbegin(&gtod->lock);

secs=gtod->wall_time_sec;

ns=gtod->wall_time_nsec+vgetns();

secs+=gtod->wall_to_monotonic.tv_sec;

ns+=gtod->wall_to_monotonic.tv_nsec;

} while (unlikely(read_seqretry(&gtod->lock,seq)));

/*wall_time_nsec,vgetns(), andwall_to_monotonic.tv_nsec

*are all guaranteedtobe nonnegative.

*/

while (ns>=NSEC_PER_SEC) {

ns-=NSEC_PER_SEC;

++secs;

}

ts->tv_sec=secs;

ts->tv_nsec=ns;

return 0;

}

这个代码读取墙上时间,然后加上相对于单调时间的便宜,从而得到单调时间,但是这里并没有考虑ntp通过adjtimex()调整小的时间偏差的情况,所以这个仍然不是绝对的单调递增。

三、内核clock_gettime系统调用

在kernel/posix-timers.c中内核实现了clock_gettime的系统调用,包括CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_MONOTONIC_RAW、CLOCK_REALTIME_COARSE、CLOCK_MONOTONIC_COARSE、CLOCK_BOOTTIME等类型,这里我们看一下CLOCK_MONOTONIC_RAW的实现

点击(此处)折叠或打开

struct k_clock clock_monotonic_raw = {

.clock_getres = hrtimer_get_res,

.clock_get = posix_get_monotonic_raw,

};

posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);

/*

* Get monotonic-raw time for posix timers

*/

static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp)

{

getrawmonotonic(tp);

return 0;

}

/**

* getrawmonotonic - Returns the raw monotonic time in a timespec

* @ts: pointer to the timespec to be set

*

* Returns the raw monotonic time (completely un-modified by ntp)

*/

void getrawmonotonic(struct timespec *ts)

{

unsigned long seq;

s64 nsecs;

do {

seq = read_seqbegin(&xtime_lock);

nsecs = timekeeping_get_ns_raw();

*ts = raw_time;

} while (read_seqretry(&xtime_lock, seq));

timespec_add_ns(ts, nsecs);

}

EXPORT_SYMBOL(getrawmonotonic);

static inline s64 timekeeping_get_ns_raw(void)

{

cycle_t cycle_now, cycle_delta;

struct clocksource *clock;

/* read clocksource: */

clock = timekeeper.clock;

cycle_now = clock->read(clock);

/* calculate the delta since the last update_wall_time: */

cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;

/* return delta convert to nanoseconds using ntp adjusted mult. */

return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);

}

四、关于wall time和monotonic timewall time:xtime,取决于用于对xtime计时的clocksource,它的精度甚至可以达到纳秒级别,内核大部分时间都是使用xtime来获得当前时间信息,xtime记录的是自1970年当前时刻所经历的纳秒数。monotonic time: 该时间自系统开机后就一直单调地增加(ntp adjtimex会影响其单调性),它不像xtime可以因用户的调整时间而产生跳变,不过该时间不计算系统休眠的时间,也就是说,系统休眠时(total_sleep_time),monotoic时间不会递增。

raw monotonic time: 该时间与monotonic时间类似,也是单调递增的时间,唯一的不同是,raw monotonic time不会受到NTP时间调整的影响,它代表着系统独立时钟硬件对时间的统计。

boot time:与monotonic时间相同,不过会累加上系统休眠的时间(total_sleep_time),它代表着系统上电后的总时间。

五、总结

在linux下获取高精度单调递增的时间,只能使用syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &monotonic_time)获取!

linux 单调时间实现原理,Linux系统下的单调时间函数相关推荐

  1. Linux(CentOS 7_x64位)系统下安装RDkit(修正)

    Linux(CentOS 7_x64位)系统下安装RDkit(修正) 一.RDKit简介 Linux(CentOS 7_x64位)系统下安装RDkit点击打开链接 前面写的一篇CentOS 7下安装R ...

  2. Linux中assert头文件,linux系统下如何使用assert函数

    linux系统下如何使用assert函数 只要看得懂程序的人都知道assert,在Windows下使用VC编写,使用assert之后,只需在IDE中设置为debug版或者是release版,编译器就会 ...

  3. linux中安装多个mysql_liunx系统下安装多个MySql数据库并做主从配置

    在网上搜索了很多资料,都没有看到像样的文档,思路不是很清晰,对第一次安装的朋友来说较为困难,经过长时间的安装尝试和查询网上零碎的知识点,终于成功的完成Linux系统下多MySql数据库安装和主从配置, ...

  4. linux 测试cpu计算圆周率_Linux系统下的CPU、内存、IO、网络的压力测试

    这里将告诉您Linux系统下的CPU.内存.IO.网络的压力测试,具体完成步骤:本文转载自:小豆芽博客 一.对CPU进行简单测试: 1.通过bc命令计算特别函数 例:计算圆周率 echo " ...

  5. win7 制作linux u盘安装教程,win7系统下u盘安装linux centos7,详细步骤,亲测

    近段时间想在自己的win7电脑上安装个linux双系统,于是下载了linux centos7这个版本,折腾了两天,网上的各种帖子看了不少,也遇到很多问题,幸运的是终于装成功了,下面就说明一下安装的整个 ...

  6. Linux(CentOS 7_x64位)系统下安装GaussView5

    GaussView GaussView是一个专门设计与高斯配套使用的软件,其主要用途有两个:构建高斯的输入文件和以图的形式显示高斯计算的结果.除了可以自己构建输入文件外,GaussView还可读入Ch ...

  7. xp下添加linux启动,如何在windows xp系统下安装linux???

    我刚刚想开始学linux,请教如何安装! | 我今天才安装了Redhat 9.0. LINUX不可能在WINDOWS下安装. 比较简单的方法是先在XP下用PQMAGIC分好区 boot  ext3 1 ...

  8. linux 自动安装mysql数据库_linux系统下源码安装mysql5.6数据库

    linux系统下源码安装mysql5.6数据库 下载mysql数据库相关软件包(百度云盘:http://pan.baidu.com/s/1bnL31c7) 从mysql 5.5版本开始,mysql源码 ...

  9. linux安装文泉字体,Linux_Linux系统下的Emacs字体配置,安装步骤:   1、安装文泉 - phpStudy...

    Linux系统下的Emacs字体配置 安装步骤: 1.安装文泉驿字体,这个在F8中已经缺省安装了.如果要手动安装的话,这样:yum -y install wqy-bitmap-fonts 2.执行fc ...

最新文章

  1. docker 异常:“fork/exec /proc/self/exe: no such file”
  2. Python基础(10) - 异常
  3. 手把手教你写平衡二叉树
  4. 计算机 旧词新说_如何使旧计算机再次有用
  5. python 处理CSV数据
  6. 高清电视开播:大多用户仍难跨入
  7. 华硕服务器主板型号命名规则,详细解读主板厂商命名规则——华硕篇
  8. 2019年春招汇总,技术类校招社招千道面试题,几百份大厂面经(附答案+考点)
  9. 角度与弧度的转换 C语言
  10. 山东省计算机软件比赛,山东省大学生软件设计大赛报名通知
  11. poj 3626 Mud Puddles
  12. COLD:中文冒犯性语言检测数据集
  13. 大数据学习——hive阶段:启动HiveServer2启动报TezConfiguration类NoClassDefFoundError错误
  14. 新办的卡为什么显示无服务器,为什么插入卡后显示无服务,有时有有时又没有?...
  15. c语言编译作用,叙述 C语言编译
  16. 阿里妈妈免费网站Flash动画广告牌制作
  17. python半径为3圆形区域边界曲线_OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓...
  18. codeforces 295B B. Greg and Graph(floyd+dp)
  19. PL/SQL Developer 注册机+汉化包+用户指南
  20. 使用立体声混音(Stereo Mix)录制音频

热门文章

  1. oracle左联表示,oracle 笔记 IX 之内联、左联、右联
  2. Java 位运算符的基本用法【1】
  3. TypeScript1-TypeScript 简介及环境搭建
  4. 【DELM回归预测】多元宇宙优化算法改进深度学习极限学习机数据回归预测【含Matlab源码 2230期】
  5. 基于bootstrap的前端分页。带省略号和上下页。
  6. servlet中@webServlet注解出错导致404
  7. 查询分页的几种sql语句
  8. 优秀团队建设-美国式团队!
  9. Matlab:实现返回所有波束的方位角和仰角对(附完整源码)
  10. SQL小试:每天的领导和合伙人