欢迎转载,转载请注明出处: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
    这个函数的实现如下:

点击(此处)折叠或打开

  1. notrace static noinline int do_monotonic(struct timespec *ts)
  2. {
  3. unsigned long seq, ns, secs;
  4. do {
  5. seq = read_seqbegin(&gtod->lock);
  6. secs = gtod->wall_time_sec;
  7. ns = gtod->wall_time_nsec + vgetns();
  8. secs += gtod->wall_to_monotonic.tv_sec;
  9. ns += gtod->wall_to_monotonic.tv_nsec;
  10. } while (unlikely(read_seqretry(&gtod->lock, seq)));
  11. /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
  12. * are all guaranteed to be nonnegative.
  13. */
  14. while (ns >= NSEC_PER_SEC) {
  15. ns -= NSEC_PER_SEC;
  16. ++secs;
  17. }
  18. ts->tv_sec = secs;
  19. ts->tv_nsec = ns;
  20. return 0;
  21. }

这个代码读取墙上时间,然后加上相对于单调时间的便宜,从而得到单调时间,但是这里并没有考虑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的实现

点击(此处)折叠或打开

  1. struct k_clock clock_monotonic_raw = {
  2. .clock_getres = hrtimer_get_res,
  3. .clock_get = posix_get_monotonic_raw,
  4. };
  5. posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);
  6. /*
  7. * Get monotonic-raw time for posix timers
  8. */
  9. static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp)
  10. {
  11. getrawmonotonic(tp);
  12. return 0;
  13. }
  14. /**
  15. * getrawmonotonic - Returns the raw monotonic time in a timespec
  16. * @ts: pointer to the timespec to be set
  17. *
  18. * Returns the raw monotonic time (completely un-modified by ntp)
  19. */
  20. void getrawmonotonic(struct timespec *ts)
  21. {
  22. unsigned long seq;
  23. s64 nsecs;
  24. do {
  25. seq = read_seqbegin(&xtime_lock);
  26. nsecs = timekeeping_get_ns_raw();
  27. *ts = raw_time;
  28. } while (read_seqretry(&xtime_lock, seq));
  29. timespec_add_ns(ts, nsecs);
  30. }
  31. EXPORT_SYMBOL(getrawmonotonic);
  32. static inline s64 timekeeping_get_ns_raw(void)
  33. {
  34. cycle_t cycle_now, cycle_delta;
  35. struct clocksource *clock;
  36. /* read clocksource: */
  37. clock = timekeeper.clock;
  38. cycle_now = clock->read(clock);
  39. /* calculate the delta since the last update_wall_time: */
  40. cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
  41. /* return delta convert to nanoseconds using ntp adjusted mult. */
  42. return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
  43. }

四、关于wall time和monotonic time
    wall 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系统下的单调时间函数的更多相关文章

  1. Unix/Linux系统下获得时间戳函数

    在Unix/Linux系统下,使用gettimeofday函数来获得当前系统的时间戳,精度可达到微秒(microsecond,即μs)级别. 通过结构体timeval来存放当前时间戳的信息: #ifn ...

  2. 深入理解linux系统下proc文件系统内容

    深入理解linux系统下proc文件系统内容 内容摘要:Linux系统上的/proc目录是一种文件系统,即proc文件系统. Linux系统上的/proc目录是一种文件系统,即proc文件系统.与其它 ...

  3. Linux系统下如何优雅地关闭Java进程?

    资料出处: http://www.sohu.com/a/329564560_700886 https://www.cnblogs.com/nuccch/p/10903162.html 前言 Linux ...

  4. 在Linux系统下运行微信Web开发者工具

    微信Web开发者工具只有window版本和mac版本,如果想要在Linux系统下运行微信Web开发者工具,需要花费很大周折. 注:带 * 的步骤或文件为不确定是否管用的步骤或文件.本人系统为Linux ...

  5. linux系统下的软连接与硬链接

    前几天在linux系统下安装mongoDB,然后运行脚本导入数据的时候遇到了链接库查询不到的情况,如图 1所示.当时是通过创建软连接的方式解决的这个问题.虽然,通过网上的教程解决了这个问题,但是对于软 ...

  6. Linux系统下Redis安装(一)

    最近项目要使用Redis,特将这段时间将Redis的学习经验与大家分享,算是对这段时间学习成果的总结和技术提炼,不足之处还望大家批评指正. 项目背景: 有些很少改动的数据和经常使用的数据(例如系统中下 ...

  7. Linux系统下Apache2.4.17的安装过程

    Linux系统下安装Apache Server2.4.17.还是先声明一下,Linux命令我不进行讲解,因为我不是讲Linux命令的.有需要注意的地方,我会上图,没什么值得的注意的地方,我就不上图了. ...

  8. Linux系统下fd分配的方法

    最近几天在公司里写网络通讯的代码比较多,自然就会涉及到IO事件监测方法的问题.我惊奇的发现select轮训的方法在那里居然还大行其道.我告诉他们现在无论在Linux系统下,还是windows系统下,s ...

  9. Linux系统下查看某文件修改的时间戳

    Linux系统下查看某文件修改的时间戳查看文件时间戳命令:stat awk.txt File: `awk.txt' Size: 20              Blocks: 8          I ...

随机推荐

  1. js28--适配器模式

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  2. inflater-布局转化实现

    通俗的说,inflate就相当于将一个xml中定义的布局找出来.因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组件 ...

  3. Dcloud课程9 天气小助手如何实现

    Dcloud课程9 天气小助手如何实现 一.总结 一句话总结:调用天气的接口,如果网上找不到好用的,而如果仅仅是测试,那就自己写一个简单的接口就可以了. 1.dcloud中的css样式怎么调? 和网页 ...

  4. Zabbix监控告警

    一 钉钉告警 1.1.1 添加钉钉机器人 发起群聊 创建完群聊选择,机器人管理 选择你要绑定的群聊 复制下面地址留用 1.1.2 编写钉钉告警脚本 安装requests库,HTTP客户端, # yum ...

  5. Exchanging Partitions and Subpartitions with Tables--官方文档

    原文地址:https://dev.mysql.com/doc/refman/5.6/en/partitioning-management-exchange.html In MySQL 5.6, it ...

  6. Appium_python3使用汇总

    1. 对webview页面元素的处理self.driver.switch_to.context("WEBVIEW_com.aaa.bbb")source = self.driver ...

  7. ASP.net 环境搭建

    https://www.cnblogs.com/leizhanjun/p/6081928.html

  8. 洛谷——P1096 Hanoi双塔问题

    https://www.luogu.org/problem/show?pid=1096 题目描述 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个 ...

  9. 51Nod——N1118 机器人走方格

    https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1118 基准时间限制:1 秒 空间限制:131072 KB 分值: 0  ...

  10. JS概述

             从Asp.NET跨越到JavaScript.这既是一个新的领域也是一个非常熟悉的地方,新是由于不知道什么是JavaScript,首先来了解一下什么是JavaScript.       ...