【问题标题】:Why are nanosleep() and usleep() too slow?为什么 nanosleep() 和 usleep() 太慢了?
【发布时间】:2010-05-27 13:13:25
【问题描述】:

我有一个程序可以生成要发送到接收器的数据包。我需要一种有效的方法来在每个数据包的发送之间引入一个小的延迟,以免超出接收器。我试过 usleep() 和 nanosleep() 但它们似乎太慢了。我已经实现了一个繁忙的等待循环并且取得了更大的成功,但我知道这不是最有效的方法。我对任何人尝试做我正在做的事情的经历感兴趣。其他人是否认为 usleep() 和 nanosleep() 适合此类应用程序?

谢谢,

丹尼·勒沃林

【问题讨论】:

  • 问题很模糊——你需要多长时间的延迟,为什么你认为 nanosleep/usleep 不能提供这种延迟?
  • 显然,我们不知道你在做什么的细节,但我认为 nanosleep 就足够了。你的睡眠需要多准确?操作系统将保证至少会发生请求的延迟时间 - 但它不会对超出睡眠请求的时间量做出类似的保证。
  • 在我的 Raspberry Pi 上,调用 nanosleep 需要超过 73us。我想我也必须去忙循环。

标签: c debian


【解决方案1】:

睡眠功能在很短的时间间隔内的行为很大程度上取决于内核版本和配置。

如果您有一个“tickless”内核 (CONFIG_NO_HZ) 和高分辨率计时器,那么您可以预期睡眠非常接近您的要求。

否则,您通常会以定时器中断的粒度结束睡眠。定时器中断间隔是可配置的 (CONFIG_HZ) - 10ms、4ms、3.3ms 和 1ms 是常见的选择。

【讨论】:

  • 这个答案似乎是在假设用户正在运行哪个操作系统。
  • 它是 Debian。我应该更清楚。我认为这是问题所在。感谢您的回复。
【解决方案2】:

假设您无法使用其他评论者提到的更高级别的方法,那么嵌入式/微控制器领域的常见方法是创建所需长度的 NOP 循环。

NOP 操作需要一个 CPU 周期,并且在嵌入式环境中,您通常可以准确地知道处理器运行的时钟速度,因此您可以使用简单的 for-loop 包含 _NOP() 或者只有很短的延迟是必需的,然后不要打扰循环,只需添加所需的 nop 数量即可。

regTX = 0xFF;  // Transmit FF on special register

// Wait three clock cycles
_NOP();
_NOP();
_NOP();

regTX = 0x00; // Transmit 00

【讨论】:

    【解决方案3】:

    这似乎是一个糟糕的设计。理想情况下,接收者会将它接收到的任何额外数据排队,然后在单独的线程中进行消息处理。通过这种方式,它可以处理突发数据,而无需依赖发送者来限制其请求。

    但是,如果(例如)您无法控制接收器的代码,或者这是一个嵌入式应用程序,那么这种方法可能不实用。

    【讨论】:

    • 您假设接收器是某处计算机上的一些软件。如果某些硬件设备对传入的数据包只有有限的缓冲区怎么办?
    • 绝对 - 我希望 OP 可以在他的问题中澄清这一点。
    【解决方案4】:

    我可以在这里为 Solaris 说话,因为它使用操作系统计时器来唤醒睡眠呼叫。默认情况下,最短等待时间为 10 毫秒,无论您在 usleep 中指定什么内容。但是,您可以使用/etc/system 配置文件中的参数hires_tick = 1(1ms 唤醒)和hires_hz = 来增加定时器唤醒调用的频率。

    【讨论】:

      【解决方案5】:

      而不是在数据包级别做事情,您需要担心诸如超出接收器之类的事情。为什么不使用 TCP 流来传输数据?让 TCP 处理诸如流量控制和数据包重传之类的事情。

      如果您已经在分组化方法上投入了大量资金,那么您始终可以在 TCP 之上使用一个层从 TCP 流中提取原始数据包,并将其提供给您现有的函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-08
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多