我正在开发游戏服务器,这是用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;
}
它的运行结果:
$ ./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
我也尝试使用函数select()
,但结果与sleep()
相同。
请解释一下,我的代码有什么问题。
P.S:
$ 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
答案 0 :(得分:11)
非实时系统上的休眠功能无法保证在指定的时间内休眠;在繁忙的系统上,只有在时间片开始时才会唤醒进程。或者,as the man page puts it,“系统活动可能会以不确定的数量延长睡眠时间。”
接近10毫秒的数量听起来像kern.hz
频率降低到100,as some recommend for VM setups。
此问题的经典解决方法是Ofir提供的解决方法:指定剩余的睡眠时间,而不是指定固定的睡眠间隔。平均而言,您的循环将每20毫秒运行一次,这是您最有可能实现的目标。
答案 1 :(得分:10)
根据对clock_gettime的调用
而不是睡眠20000秒,而是在你想要再次运行的时候休眠一段时间。即:
usleep( lasttime+20000-now ); // But make sure you don't sleep when the result is negative
这不是你的代码有问题,但实际的睡眠调用,读取时间等需要时间,系统无论如何都无法在确切的时间内睡眠,除非它是其确切时钟的倍数周期
答案 2 :(得分:0)
在usleep
函数中1000000 = 1秒。
尝试相应地更改您的代码。所以:
usleep(1000000) // generates 1 second delay