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

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

最后,如果我有一个NTP守护进程定期调整系统时间,这些调整如何与每个CLOCK_REALTIME和CLOCK_MONOTONIC交互?


当前回答

CLOCK_REALTIME受NTP影响,可以向前和向后移动。CLOCK_MONOTONIC不是,它每滴答一滴答地前进。

其他回答

不好意思,没有声望可以添加这条评论。所以这是一个互补答案。

取决于你调用clock_gettime()的频率,你应该记住,在VDSO中只有一些“时钟”是由Linux提供的(即不需要一个系统调用的所有开销——当Linux添加防御来防止类似幽灵的攻击时,这只会变得更糟)。

虽然clock_gettime(CLOCK_MONOTONIC,…),clock_gettime(CLOCK_REALTIME,…)和gettimeofday()总是非常快(由VDSO加速),但对于例如clock_单调ic_raw或任何其他POSIX时钟来说不是这样的。

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

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

以下是“证据”(GitHub,以防止机器人接近kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7

除了伊格纳西奥的答案,CLOCK_REALTIME还可以向前跳跃,偶尔也可以向后跳跃。CLOCK_MONOTONIC两者都没有;它只是继续前进(尽管它可能在重新启动时重置)。

一个健壮的应用程序需要能够容忍CLOCK_REALTIME偶尔向前跳跃(也许向后非常轻微,非常偶尔,尽管这是一个边缘情况)。

想象一下当你挂起你的笔记本电脑时会发生什么——CLOCK_REALTIME跟随resume向前跳转,而CLOCK_MONOTONIC没有。在虚拟机上试试。

CLOCK_REALTIME表示机器对当前挂钟时间的最佳猜测。正如Ignacio和MarkR所说,这意味着CLOCK_REALTIME可以随着系统时间(包括NTP)的改变而向前和向后跳转。

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

如果希望计算在一台机器上观察到的两个事件之间的时间,而不需要重新启动,那么CLOCK_MONOTONIC是最佳选择。

注意,在Linux上,CLOCK_MONOTONIC不测量挂起所花费的时间,尽管根据POSIX定义它应该测量。您可以将linux特定的CLOCK_BOOTTIME用于在挂起期间保持运行的单调时钟。

CLOCK_REALTIME受NTP影响,可以向前和向后移动。CLOCK_MONOTONIC不是,它每滴答一滴答地前进。

CLOCK_REALTIME和MONOTONIC之间有一个很大的区别。CLOCK_REALTIME可以根据NTP向前跳或向后跳。 缺省情况下,NTP允许时钟速率的加速或减速不超过0.05%,但NTP不能使单调时钟向前或向后跳变。