CLOCK_REALTIME和CLOCK_MONOTONIC之间的区别?

NPE*_*NPE 185 linux

你能解释一下Linux上返回的时钟CLOCK_REALTIMECLOCK_MONOTONIC时钟之间的区别clock_gettime()吗?

如果我需要计算外部源产生的时间戳与当前时间之间的经过时间,那么哪个是更好的选择?

最后,如果我有一个NTP守护进程周期性地调整系统时间,如何做这些调整与每个交互CLOCK_REALTIMECLOCK_MONOTONIC

caf*_*caf 216

CLOCK_REALTIME代表机器对当前挂钟,时间时间的最佳猜测.正如IgnacioMarkR所说,这意味着CLOCK_REALTIME随着系统时钟的变化(包括NTP),它可以向前和向后跳跃.

CLOCK_MONOTONIC表示从过去的某个任意固定点开始的绝对经过的挂钟时间.它不受系统时钟变化的影响.

如果要计算在一台计算机上观察到的两个事件之间经过的时间而没有重新启动,CLOCK_MONOTONIC则是最佳选择.

请注意,在Linux上,CLOCK_MONOTONIC不会测量挂起所花费的时间,尽管它应该通过POSIX定义.您可以使用特定CLOCK_BOOTTIME于Linux 的单调时钟在挂起期间保持运行.

  • 当然,让CLOCK_MONOTONIC_PARBOILED受到NTP纠正频率误差的影响可能会很有意思,但不会受到纠正相位误差的影响,但这对于一个可疑的增益来说是很复杂的:) (21认同)
  • @JosephGarvin的某些"更好"的价值,或许 - CLOCK_MONOTONIC_RAW可能会快速或慢速实时运行几百(或几百)百万分之一,其速率可能会因温度或电压等环境条件(或偷窃时间)而变化虚拟机).在正常工作的机器上,NTP尽最大努力减轻所有这些因素,因此CLOCK_MONOTONIC更接近于*true*经过的时间. (13认同)
  • 请注意,在较新的内核上,CLOCK_MONOTONIC_RAW可用,甚至更好(无NTP调整). (11认同)
  • 我认为提及CLOCK_REALTIME受闰秒影响也很重要.这意味着每次插入闰秒时它*将*生成双时间戳.上次这发生在2012年6月30日和相当多的软件[遇到麻烦](https://en.wikipedia.org/wiki/Leap_second#Examples_of_problems_caused_by_the_leap_second). (3认同)

use*_*100 36

Robert Love的书LINUX系统编程第2版,专门解决了您在第11章开头的问题,第363页:

单调时间源的重要方面不是当前值,而是时间源严格线性增加的保证,因此可用于计算两次采样之间的时间差.

也就是说,我相信他假设这些进程在同一个操作系统实例上运行,因此您可能希望定期运行校准以估算漂移.


Ign*_*ams 21

CLOCK_REALTIME受NTP影响,可以向前和向后移动.CLOCK_MONOTONIC不是,并且每剔一个刻度.

  • CLOCK_MONOTONIC受NTP时间调整(时间回转)的影响.然而,它不会跳跃. (13认同)
  • 但是在较新的内核上有CLOCK_MONOTONIC_RAW,它实际上不受NTP的影响. (3认同)
  • “tick”——对 Linux/amd64 上的一个刻度有多大/多长/CPU 指令有什么粗略的了解吗?或者我可以在哪里获得有关这方面的文档? (2认同)

Mar*_*rkR 17

除了伊格纳西奥的回答之外,CLOCK_REALTIME还可以在飞跃中前进,偶尔也会倒退.CLOCK_MONOTONIC没有; 它只是继续前进(虽然它可能在重新启动时重置).

一个强大的应用程序需要能够容忍CLOCK_REALTIME偶尔向前跳跃(也许偶尔会稍微向后倾斜,尽管这更像是一个边缘情况).

想象一下,当你暂停你的笔记本电脑时会发生什么 - CLOCK_REALTIME在简历之后向前跳,CLOCK_MONOTONIC但事实并非如此.在VM上试用它.

  • @Benubird:程序启动时它不会从0开始.那是'CLOCK_PROCESS_CPUTIME_ID`.快速测试:`$ perl -w -MTime :: HiRes = clock_gettime,CLOCK_MONOTONIC -E'说clock_gettime(CLOCK_MONOTONIC)' - > 706724.117565279.这个数字与Linux上的系统正常运行时间相匹配,但该标准表明它是随意的. (17认同)
  • 顺便说一句,我不相信`CLOCK_MONOTONIC`停止暂停/恢复的Linux行为符合POSIX标准.它应该是过去一个固定点以来的时间,但是暂停/恢复暂停时钟会打破这个时间. (4认同)
  • 程序启动时,CLOCK_MONOTONIC从0开始; 它不适用于进程间使用. (3认同)

Cir*_*四事件 9

POSIX 7http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html上指定:

CLOCK_REALTIME:

该时钟代表测量系统实时的时钟.对于此时钟,clock_gettime()返回并由clock_settime()指定的值表示自Epoch以来的时间量(以秒和纳秒为单位).

CLOCK_MONOTONIC (可选功能):

对于此时钟,clock_gettime()返回的值表示自过去未指定的点(例如,系统启动时间或Epoch)以来的时间量(以秒和纳秒为单位).系统启动时间后,这一点不会改变.无法通过clock_settime()设置CLOCK_MONOTONIC时钟的值.

clock_settime()给出了一个重要提示:POSIX系统能够随意改变CLOCK_REALITME它,因此不要依赖它既不连续也不向前流动.NTP可以使用clock_settime(),也可能只会影响CLOCK_REALITME.

Linux内核实现似乎将启动时间作为以下时代CLOCK_MONOTONIC:CLOCK_MONOTONIC的起点


小智 8

抱歉,没有声誉可以将此添加为评论。所以它是一个补充答案。

根据您调用的频率clock_gettime(),您应该记住,VDSO 中的 Linux 只提供了一些“时钟”(即不需要系统调用,而系统调用的所有开销只有一个 - 当 Linux 添加时,情况只会变得更糟防御类似幽灵攻击的防御措施)。

虽然clock_gettime(CLOCK_MONOTONIC,...)clock_gettime(CLOCK_REALTIME,...)、 和gettimeofday()总是非常快(由 VDSO 加速),但对于 CLOCK_MONOTONIC_RAW 或任何其他 POSIX 时钟来说,情况并非如此。

这可能会随着内核版本和体系结构的变化而改变。

尽管大多数程序不需要注意这一点,但由 VDSO 加速的时钟可能会出现延迟峰值:如果在内核使用时钟计数器更新共享内存区域时恰好命中它们,则它必须等待内核完成。

这是“证据”(GitHub,让机器人远离 kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7