2012-10-08 24 views
10

Estoy desarrollando el servidor del juego, que está escrito en C. Y necesito desarrollar un ciclo con una cierta frecuencia (50 veces por segundo) para realizar un algoritmo. El problema es que no puedo pausar el programa para un intervalo de tiempo exacto: 20000 microsegundos. La función usleep(20000) se ejecuta a unos 30000 microsegundos. El resultado es siempre más en 10000 microsegundos de lo esperado.tiempo de retraso en C. usleep

Aquí está mi ejemplo simple de código:

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

} 

Y el resultado de que se está ejecutando:

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

También probé a la función select() usar, pero resultado es el mismo que con el sleep() .

Explícame, por favor, qué pasa con mi código.

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

Relacionados: [Dormir por una duración exacta] (http://stackoverflow.com/q/5209408/237483) –

Respuesta

9

En lugar de dormir para 20000 useconds, dormir durante el tiempo que queda hasta que se desea ejecutar de nuevo, basado en la llamada a clock_gettime

Es decir:

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

No es que su código tenga un problema, pero la llamada real para dormir, leer la hora, etc. toma tiempo, y el sistema no puede dormir la hora exacta de todos modos a menos que sea un múltiplo de su ciclo de reloj exacto

11

No se garantiza que las funciones de dormir en sistemas que no son en tiempo real duerman el período exacto especificado; en un sistema ocupado, el proceso se activará solo cuando comience su segmento de tiempo. O bien, as the man page puts it, "la actividad del sistema puede alargar la suspensión en una cantidad indeterminada".

La cantidad de cerca de 10 ms parece que la frecuencia kern.hz se reduce a 100, as some recommend for VM setups.

La solución clásica para este problema es la ofrecida por Ofir: en lugar de especificar un intervalo de sueño fijo, especifique el tiempo restante para dormir. En promedio, su bucle se ejecutará cada 20 ms, que es lo que más desea lograr.

+5

Para agregar a la respuesta: los comandos de suspensión liberan el procesador durante un tiempo de duración establecido. Durante este retraso, el proceso no solicita el procesador y no forma parte de las elecciones del proceso del planificador. Una vez que el temporizador expira, el proceso volverá a entrar en competencia con el otro proceso para el uso de la CPU. La demora adicional proviene de la opción del planificador para elegir su programa o no en cada momento de elección. –