gettimeofday在Linux中奇怪的行为

时间:2012-10-17 10:01:37

标签: c++

最近,我一直试图使用挂钟作为参考来创建一个等待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()每25ms调用一次。然而它确实会吃掉所有的CPU(如你所料),所以很明显这不是一个好主意。

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

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

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

我知道gettimeofday容易受到NTP更新等攻击...所以我尝试使用clock_gettime但是在我的系统上连接-ltr会导致问题所以我不认为这是一个选项。 / p>

有谁知道我做错了什么?

2 个答案:

答案 0 :(得分:2)

这里缺少的部分是内核如何根据时间片进行线程调度。粗略地说,如果您在时间片的开始处睡眠1ms并且调度以35ms的时钟速率完成,则您的线程可能不会再执行35ms。如果你睡眠40ms,你的线程可能不会再执行70ms。如果不更改调度,则无法真正更改,但由于系统的整体性能影响,不建议这样做。你可以使用一个“高分辨率”计时器,但通常是在一个紧凑的循环浪费循环中实现的“虽然它还没有时间,但是咀嚼CPU”,所以这也不是很理想。

如果您使用高分辨率时钟并在DoStuff循环内经常查询它,您可能会玩一些技巧,比如运行30ms,然后进行一次睡眠(1),这可以有效地放弃你的线程剩下的timeslice(例如5ms)让其他线程运行。如果你愿意,那种合作/先发制人的多任务处理。你仍然有可能长时间不回去工作......

答案 1 :(得分:1)

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