【问题标题】:Nanosecond Precision Variable Timer for Kernel 4.X using CLOCK_REALTIME使用 CLOCK_REALTIME 的内核 4.X 的纳秒级精度变量计时器
【发布时间】:2017-06-25 03:10:09
【问题描述】:

我一直在研究计时器,但仍然无法为我的情况找到一个有希望的解决方案。

基本上,我想在特定时间发送数据包。 例如:

第一个数据包在 1486500720.000000000

-> 等待 -> nanosleep(1000000000)

第二个数据包在 1486500721.000000000

-> 等待 -> nanosleep(1000000000)

第 3 个数据包位于 1486500722.000000000

-> 等待 -> nanosleep(1000000000)

第 4 个数据包位于 1486500723.000000000

它们之间的时间间隔正好是 1.000000000 秒,但是当我发送数据包时,每次都需要不同的时间。

例如对于第一个数据包,发送它需要 0.005025045 秒,然后 nanosleep 开始。

所以,我的第二个数据包发送到 486500721.005025045 而不是 1486500721.000000000。

所以每次我必须通过使用 clockgettime(CLOCK_REALTIME) 来调整 nanosleep 值,方法是减去包含 gettime 命令开销的偏移量的剩余时间。

由于我必须在一个具有纳秒精度的循环中执行此操作(我知道这是不可能的,但我希望它尽可能具体),我使用简单的 for 循环。

我的问题是有没有更好的方法来更精确地做到这一点?我使用的是 Kernel 4.4,所以您是否知道任何适用于较新内核的方法或任何其他可能比我的更精确的方法?

【问题讨论】:

  • timer_create()为自己设置一个计时器。
  • @EOF:这并不能保证更少的抖动。 OP:在 Linux 或任何其他成熟的操作系统中,您无法达到纳秒级精度。即使对于 RTOS,也有一个下限,很可能比这大得多(RT 不保证“无抖动”)。这听起来像是一个 XY 问题。您的实际和具体问题是什么?
  • @Olaf:当然,你会得到 statistical 抖动。但与 OP 当前的方法不同的是,阶段不应有太多(任何)系统性变化。
  • @EOF:这取决于 OP 想要什么。从问题上看不清楚。
  • @Olaf:在我看来,OP 想要发送多个数据包,每秒一个。对我来说似乎相当明显。

标签: c linux timer linux-kernel kernel


【解决方案1】:

您应该使用clock_nanosleep,它允许等待绝对时间,而不是nanosleep,它只使用相对时间。但是,您无法获得所需的精确度。时钟到期后返回用户空间至少需要几百纳秒,如果不是一千或更多。在你醒来后发送数据包也会有不可预知的延迟。

您最多可以将唤醒时间调整为“足够接近”以达到您的目的。

【讨论】:

  • 我建议使用timer_create() 设置一个间隔计时器。
  • @EOF:为什么?我强烈建议不要这样做,因为信号处理程序是一个糟糕的运行环境——调用clock_nanosleep 的线程对于如何与程序的其余部分进行交互来说是一个更好的环境。两者都不应该比另一个有任何性能/时间优势。
  • 您不必在信号处理程序中运行任何代码,timer_create() 可以在线程上下文中运行代码。或者,您可以sigwait()。无论哪种方式,使用间隔计时器都可以避免将等待时间移动到代码在等待之间执行的时间。
  • @EOF:您的 cmets 表明该主题缺乏研究。 glibc 的定时器线程交付实现在每次定时器到期时创建新线程,增加 巨大 延迟并在线程创建失败时静默丢弃定时器到期。这是无法使用的坏。 clock_nanosleep,具有绝对到期时间,已经避免了必须改变等待时间,因为你没有通过唤醒时间;你过了一个起床时间。
  • 感谢您采用这种方法。今天早上我也想通了。这正是我想要的。非常感谢你:-)
猜你喜欢
  • 2018-02-16
  • 1970-01-01
  • 2015-02-27
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-06
  • 2017-04-22
相关资源
最近更新 更多