当前位置: 首页 > 面试题库 >

如何获得linux gettimeofday()的微秒时间,其精度是多少?

丁经国
2023-03-14
问题内容

挂钟时间通常由系统RTC提供。这主要仅提供时间到毫秒范围,并且通常具有10到20毫秒的粒度。但是,通常报告说gettimeofday()的分辨率/粒度在几微秒的范围内。我假设微秒粒度必须来自其他来源。

如何实现gettimeofday()的微秒分辨率/粒度?

当从RTC提取到毫秒以下的部分并且从不同的硬件获取微秒时,会出现两个源的相位调整问题。这两个来源必须是synchronized某种方式。

这两个源之间的同步/定相如何完成?

编辑: 根据我在amdn提供的链接中阅读的内容,尤其是以下Intel链接,我会在这里添加一个问题:

是否gettimeofday()可以在微秒范围内提供分辨率/粒度?

编辑2: 使用更多阅读结果总结amdns 答案:

Linux仅在引导时使用实时时钟(RTC)与更高分辨率的计数器ig
Timestampcounter(TSC)进行同步。引导后,gettimeofday()将返回一个完全基于TSC值和该计数器频率的时间。frequency通过将系统时间与外部时间源进行比较,可以对TSC的初始值进行校正/校准。调整由adjtimex()函数完成/配置。内核运行一个锁相环,以确保时间结果是单调且一致的。

这样可以说gettimeofday()具有微秒的分辨率。考虑到更现代的Timestampcounter在GHz范围内运行,可获得的分辨率可能在纳秒范围内。因此,这个有意义的评论

/**
407  * do_gettimeofday - Returns the time of day in a timeval
408  * @tv:         pointer to the timeval to be set
409  *
410  * NOTE: Users should be converted to using getnstimeofday()
411  */

可以在Linux / kernel / time / timekeeping.c中找到。这表明在以后的某个时间点可能会提供更高分辨率的功能。现在getnstimeofday()仅在内核空间中可用。

但是,仔细查看所有相关代码以正确解决此问题,可以看到很多有关不确定性的注释。可能会获得微秒的分辨率。该功能gettimeofday()甚至可以在微秒范围内显示粒度。
但是: 关于 drift
TSC频率的准确度存在严重质疑,因为TSC频率的准确度无法得到校正。同样,在Linux内部处理此问题的代码的复杂性也暗示着人们相信,实际上很难正确地做到这一点。这是特别的,但并非仅由应该运行Linux的大量硬件平台引起。

结果: gettimeofday()以微秒粒度返回单调时间,但它提供的时间几乎one microsecond与任何其他时间源都没有相位。


问题答案:

如何实现gettimeofday()的微秒分辨率/粒度?

Linux在许多不同的硬件平台上运行,因此具体情况有所不同。在现代的x86平台上,Linux使用时间戳计数器(也称为)TSC,由多个以133.33
MHz运行的晶体振荡器驱动。晶体振荡器为处理器提供参考时钟,处理器将其乘以某个倍数-例如,在2.93
GHz处理器上,倍数为22。从TSC历史上看,这是不可靠的时间来源,因为实现会在处理器运行时停止计数器睡眠,或者因为处理器移动乘数以改变性能状态或变热时降低速度而导致倍数不是恒定的。现代x86处理器提供了TSC那是恒定的,不变的,不停的。在这些处理器上,这TSC是一个出色的高分辨率时钟,Linux内核在启动时确定初始近似频率。该TSC规定有gettimeofday()系统调用和纳秒分辨率为clock_gettime()系统调用微秒的分辨率。

如何实现同步?

您的第一个问题是关于Linux时钟如何提供高分辨率的,第二个问题是关于同步的,这是精度和准确性之间的区别。大多数系统都有一个由电池备份的时钟,以保持系统断电的时间。如您所料,该时钟不具有较高的准确性或精度,但是它将在系统启动时“处于正常状态”。为了获得准确性,大多数系统使用可选组件从网络上的外部源获取时间。两种常见的是

  1. 网络时间协议
  2. 精确时间协议

这些协议定义了网络上的主时钟(或原子时钟提供的时钟层),然后测量网络延迟以估计与主时钟的偏移量。一旦确定了与主机的偏移量,系统时钟便会disciplined保持其准确度。这可以通过

  1. 调整时钟(相对较大,突然且不频繁的时间调整),或
  2. Slewing 时钟(定义为在给定时间段内通过缓慢增加或减少频率来调整多少时钟频率)

内核提供adjtimex系统调用以允许时钟调节。

用于时钟调整的相关内核源文件是kernel / time.c和kernel / time /
timekeeping.c。



 类似资料:
  • 问题内容: 我必须使用MySQL开发应用程序,并且必须保存“ 1412792828893”之类的值,该值代表时间戳,但精度为毫秒。即,自1970年1月1日以来的毫秒数。我声明该行为,但不幸的是,这行不通。所有值均设置为 为了能够以这种精度保存时间戳记值,如何声明? 问题答案: 您需要使用MySQL 5.6.4或更高版本,才能声明具有小数秒时间数据类型的列。不确定您使用的版本正确吗?尝试。如果遇到错

  • 本文向大家介绍nodejs如何高精度计时(纳秒)?相关面试题,主要包含被问及nodejs如何高精度计时(纳秒)?时的应答技巧和注意事项,需要的朋友参考一下 const start = process.hrtime.bigint(); // 191051479007711n setTimeout(() => { const end = process.hrtime.bigint(); // 1910

  • 本文向大家介绍如何使用C# Stopwatch 测量微秒级精确度,包括了如何使用C# Stopwatch 测量微秒级精确度的使用技巧和注意事项,需要的朋友参考一下 跟同事讨论到- 用C# Stopwatch 取得效能数值,Stopwatch.ElapsedMilliseconds 只到毫秒(ms),如果需要更高的时间精确度(微秒μs,甚至奈秒ns),该怎么做? 原以为要费番功夫,在Stackove

  • 我正在尝试生成一个分辨率为微秒的时间戳。我试着用这个答案提取年/月/日等,来自C++中的std::chrono::time_point,还有这个:C++11实际系统时间(毫秒),但我不确定这样做是否正确: 该代码的输出为: 324760155[2019-09-15 10:09:13.324.324760][2019-09-15 10:09:13.324.324760]

  • 问题内容: 我想在Java中将双数取整,以便将其转换为最接近的十分位数,如下所示。 我该怎么办实际上我的意图是在图表上设置Y轴,如果最大值为0.1,则num_间隔将设置为.01,如果最大值为0.3,则转换为1,然后将num_间隔设置为.1,依此类推。 问题答案: 尝试将其翻译成您的语言,我已经用Matlab编写了它,但是它应该很明显 当然,这只有在积极的情况下才有效。

  • 我正在尝试创建一个程序,它将生成斐波那契序列中的数字,直到它找到序列中的1000位数字。我使用的代码运行良好并提供有效的输出,但是,我在检索每个数字的长度时遇到了麻烦;使用我已将转换为并使用方法获取长度,但是,我发现这并没有给出真正的长度,我看不出为什么。 有没有更好的方法来获取的长度?我已经读到了thBigInteger这个问题:在一个可伸缩的方法中计算小数位数 更新运行程序后输出的文本文本为: