2012-10-08 11 views
10

Ich entwickle den Spieleserver, der auf C geschrieben ist. Und ich muss einen Zyklus mit einer bestimmten Frequenz (50 mal pro Sekunde) entwickeln, um einen Algorithmus durchzuführen. Das Problem ist, dass ich das Programm für ein genaues Zeitintervall nicht anhalten kann - 20000 Mikrosekunden. Funktion usleep(20000) läuft etwa 30000 Mikrosekunden. Das Ergebnis ist immer mehr auf 10000 Mikrosekunden als erwartet.Zeitverzögerung in C. usleep

Hier ist mein einfaches Beispiel Code:

#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; 

} 

Und das Ergebnis es läuft:

$ ./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 

Ich habe auch versucht Funktion verwenden select(), sondern Ergebnis ist das gleiche wie bei den sleep() .

Erklären Sie mir bitte, was mit meinem Code nicht stimmt.

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

In Verbindung stehende: [Sleeping für eine genaue Dauer] (http://StackOverflow.com/q/5209408/237483) –

Antwort

9

Statt Schlaf für 20000 useconds, Schlaf für die Zeit nach links, bis Sie wieder ausgeführt werden soll, auf den Anruf basierend auf clock_gettime

Ie:

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

Es ist nicht so, dass Ihr Code ein Problem hat, aber der eigentliche Anruf zum Einschlafen, Lesen der Uhrzeit usw. braucht Zeit, und das System kann sowieso nicht für die genaue Zeit schlafen, es sei denn, es ist ein Vielfaches davon exakter Taktzyklus

11

Sleeping-Funktionen auf Nicht-Echtzeit-Systemen werden nicht garantiert, um genau die angegebene Zeit zu schlafen; Bei einem ausgelasteten System wird der Prozess nur dann aktiviert, wenn die Zeitscheibe beginnt. Oder, as the man page puts it, "Systemaktivität kann den Schlaf um einen unbestimmten Betrag verlängern".

Die nahe-10ms Menge klingt wie die kern.hz Frequenz wird auf 100, as some recommend for VM setups gesenkt.

Die klassische Problemumgehung für dieses Problem ist die von Ofir angebotene: Anstatt ein festes Schlafintervall anzugeben, geben Sie die verbleibende Schlafzeit an. Im Durchschnitt läuft Ihre Schleife alle 20ms, was Sie am ehesten erreichen möchten.

+5

Um die Antwort hinzuzufügen: die Schlaf-Befehle geben den Prozessor für eine festgelegte Zeitdauer. Während dieser Verzögerung fragt der Prozess nicht nach dem Prozessor und ist nicht Teil der Wahlen des Schedulerprozesses. Sobald der Timer abgelaufen ist, wird der Prozess erneut in Konkurrenz mit dem anderen Prozess für die CPU-Nutzung eintreten. Die zusätzliche Verzögerung kommt von der Wahl des Schedulers, um zu jeder Wahlzeit Ihr Programm zu wählen oder nicht. –

Verwandte Themen