2012-10-08 97 views
10

我開發遊戲服務器,這是在C.書面和我需要開發具有特定頻率的週期(每秒50次) 執行的算法。 問題是我無法將程序暫停一段確切的時間間隔--20000微秒。 函數usleep(20000)運行大約30000微秒。 結果總是比預期的要多10000微秒。時間延遲usleep

這裏是我的代碼簡單的例子:

#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()

請向我解釋我的代碼有什麼問題。

PS:

$ uname -a 
FreeBSD home.com 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012  [email protected]:/usr/obj/usr/src/sys/GENERIC amd64 
+0

相關:[睡眠一個確切的持續時間](http://stackoverflow.com/q/5209408/237483) –

回答

9

而是沉睡20000個useconds的,睡眠留到要再次運行時間的基礎上,調用clock_gettime

即:

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

這並不是說你的代碼有問題,但實際的睡眠呼叫,閱讀時間等等需要時間,而系統無論如何都不能準確地睡眠,除非它是它的倍數精確的時鐘週期

11

在非實時系統上的睡眠功能不能保證睡眠指定的確切時間;在一個繁忙的系統上,只有當時間片開始時,這個過程纔會被喚醒。或者,as the man page puts it,「系統活動可能會延長睡眠不確定的數量」。

接近10ms的量聽起來像kern.hz頻率降低到100,as some recommend for VM setups

經典的解決方法對於這個問題是由奧菲爾提供的一個:而不是指定一個固定的睡眠間隔中,指定的剩餘時間入睡。平均而言,您的循環將每20ms運行一次,這是您最想實現的目標。

+5

要添加到應答:睡眠命令釋放一組持續時間的處理器。在這段延遲期間,該進程不要求處理器,也不是調度程序進程選舉的一部分。一旦計時器到期,該進程將重新進入與CPU使用的其他進程競爭。額外的延遲來自調度員選擇在每次選舉時選擇你的節目或不選。 –