【问题标题】:gettimeofday on uLinux wierd behaviourLinux奇怪行为中的gettimeofday
【发布时间】:2012-10-17 10:01:36
【问题描述】:

最近我一直在尝试使用挂钟作为参考创建一个等待 25 毫秒的等待函数。我环顾四周,发现“gettimeofday”,但我一直遇到问题。我的代码(简化):

while(1)
{
    timeval start, end;
    double t_us;
    bool release = false;    
    while (release == false)
    {
        gettimeofday(&start, NULL);

        DoStuff();

        {
            gettimeofday(&end, NULL);
            t_us = ( (end.tv_sec - start.tv_sec) * 1000*1000) + (end.tv_usec - start.tv_usec);

            if (t_us >= 25000) //25 ms
            {
                release = true;
            }
        }
    }
}

此代码在线程 (Posix) 中运行,并且就其自身而言,运行良好。 DoStuff() 每 25 毫秒调用一次。但是,如果可以(如您所料),它确实会吃掉所有的 CPU,所以显然这不是一个好主意。

当我尝试通过添加 Sleep(1) 来限制它时;在 if 语句之后的等待循环中,整个事情减慢了大约 50%(也就是说,它每 37 毫秒左右调用一次 DoStuff。这对我来说毫无意义 - 假设 DoStuff 和任何其他线程在 (25 - 1) 毫秒 DoStuff 的调用速率不应该受到影响(允许 1ms 的误差范围)

我也尝试过 Sleep(0)、usleep(1000) 和 usleep(0),但行为是一样的。

每当另一个更高优先级的线程需要 CPU 时间(没有睡眠)时,都会发生相同的行为。就好像当线程重新启动运行时时钟停止计数一样。

我知道 gettimeofday 容易受到 NTP 更新等因素的影响...所以我尝试使用 clock_gettime 但在我的系统上链接 -ltr 会导致问题,所以我不认为这是一个选项。

有人知道我做错了什么吗?

【问题讨论】:

  • 问题中的代码是否正确? while (release == false) 似乎放错了位置。
  • 在 POSIX 平台上休眠一段时间的常用方法是使用 select 函数。另外,如果你的编译器支持它,你也有std::this_thread::sleep_for
  • @Joachim 是的,我忘记了 while 循环括号 - 已修复。

标签: c++


【解决方案1】:

这里缺少的部分是内核如何基于时间片进行线程调度。在粗略的数字中,如果您在时间片开始时休眠 1 毫秒并且调度以 35 毫秒的时钟速率完成,那么您的线程可能不会在 35 毫秒内再次执行。如果你休眠 40 毫秒,你的线程可能在 70 毫秒内不会再次执行。如果不更改调度,您无法真正更改它,但由于系统的整体性能影响,不建议这样做。您可以使用“高分辨率”计时器,但通常这是在“还没有到时候,咀嚼 CPU”的紧密循环浪费循环中实现的,因此这也不是真正可取的。

如果您使用高分辨率时钟并在 DoStuff 循环中频繁查询它,您可能会玩一些技巧,例如运行 30 毫秒,然后执行 sleep(1),这可以有效地在您的剩余时间里放弃您的线程时间片(例如 5ms)让其他线程运行。如果你愿意的话,一种合作/先发制人的多任务处理。不过,你仍然有可能在很长一段时间内无法恢复工作......

【讨论】:

    【解决方案2】:

    sleep()/usleep() 的所有变体都涉及将 CPU 让给其他可运行任务。然后,您的程序只有在内核重新调度后才能运行,在您的情况下,这似乎持续了大约 37 毫秒。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      相关资源
      最近更新 更多