C. usleep的时间延迟

And*_*rew 12 c timedelay usleep

我正在开发用C编写的游戏服务器.我需要开发一个具有特定频率(每秒50次)的循环来执行算法.问题是我无法暂停程序一段精确的时间间隔 - 20000微秒.函数usleep(20000)运行大约30000微秒.结果总是比预期的10000微秒更多.

这是我的简单代码示例:

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main( int argc, char ** argv )
{

        const unsigned long long nano = 1000000000;
        unsigned long long t1, t2;

        struct timespec tm;

        for(;;)
        {

                clock_gettime( CLOCK_REALTIME, &tm );
                t1 = tm.tv_nsec + tm.tv_sec * nano;

                usleep( 20000 );

                clock_gettime( CLOCK_REALTIME, &tm );
                t2 = tm.tv_nsec + tm.tv_sec * nano;

                printf( "delay: %ld\n", ( t2 - t1 ) / 1000 );
        }

        return 0;

}
Run Code Online (Sandbox Code Playgroud)

它运行的结果是:

$ ./a.out
delay: 29233
delay: 29575
delay: 29621
delay: 29694
delay: 29688
delay: 29732
delay: 29709
delay: 29706
delay: 29666
delay: 29702
delay: 29702
delay: 29705
delay: 29789
delay: 29619
delay: 29785
delay: 29634
delay: 29692
delay: 29708
delay: 29701
delay: 29703
Run Code Online (Sandbox Code Playgroud)

我也尝试使用函数select(),但结果与使用相同sleep().

请解释一下,我的代码出了什么问题.

PS:

$ uname -a
FreeBSD home.com 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:46:30 UTC 2012     root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64
Run Code Online (Sandbox Code Playgroud)

use*_*342 11

非实时系统上的睡眠功能无法保证在指定的时间内睡眠; 在繁忙的系统上,只有在时间片开始时才会唤醒进程.或者,正如手册页所说,"系统活动可能会以不确定的数量延长睡眠时间".

接近10毫秒的数量听起来像kern.hz频率降低到100,因为一些人推荐用于VM设置.

此问题的经典解决方法是Ofir提供的解决方法:指定剩余的睡眠时间,而不是指定固定的睡眠间隔.平均而言,您的循环将每20毫秒运行一次,这是您最有可能实现的目标.

  • 要添加答案:sleep命令会释放处理器一段时间.在此延迟期间,该过程不要求处理器,也不是调度程序进程选举的一部分.一旦计时器到期,该过程将重新进入与CPU使用的其他过程的竞争中.额外的延迟来自调度程序选择在每个选举时间选择您的程序. (5认同)

Ofi*_*fir 10

根据对clock_gettime的调用,不要睡觉20000秒,而是在你想要再次运行的时候睡觉.

即:

usleep( lasttime+20000-now ); // But make sure you don't sleep when the result is negative
Run Code Online (Sandbox Code Playgroud)

这不是你的代码有问题,但实际的睡眠调用,读取时间等需要时间,系统无论如何都无法在确切的时间内睡眠,除非它是其确切时钟周期的倍数