Cómo implementar un temporizador preciso en Linux
Al escribir programas, a menudo utilizamos temporizadores. Este artículo presentará cómo usar select para implementar un súper reloj. Usando la función de selección podemos implementar temporizadores con niveles sutiles de precisión. Además, la función de selección también es una función que usamos a menudo cuando escribimos programas sin bloqueo.
Primero, echemos un vistazo al prototipo de la función select:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
Descripción del parámetro:
El primer parámetro nfds de slect es el valor máximo del descriptor en la colección fdset más uno. fdset es una matriz de bits cuyo tamaño está limitado a __FD_SETSIZE (1024). Cada bit de la matriz de bits indica si es necesario verificar su descriptor correspondiente.
El segundo, tercer y cuarto parámetro de selección representan las matrices de bits del descriptor de archivo que deben verificarse en eventos de lectura, escritura y error, respectivamente. Estos parámetros son parámetros de entrada y salida y el kernel puede modificarlos para indicar en qué descriptores ocurrió el evento relevante. Por lo tanto, es necesario reinicializar fdset antes de cada llamada para seleccionar.
El parámetro de tiempo de espera es el período de tiempo de espera, que es una estructura modificable por el kernel que contiene el valor del tiempo restante para el tiempo de espera.
Para usar select para implementar un temporizador, necesita usar su parámetro de tiempo de espera y tenga en cuenta:
1) La función select usa la estructura timeval como parámetro.
2) La función de selección actualizará el valor de timeval y timeval guarda el valor del tiempo restante.
Si especificamos el valor del parámetro timeval y configuramos todos los demás parámetros en 0 o NULL, entonces la función de selección regresará cuando expire el tiempo y podremos usar select en consecuencia para lograr una sincronización precisa.
La estructura de timeval es la siguiente:
struct timeval{
long tv_sec;/*segundos*
long tv_usec;/ *microsegundos */
}
Podemos ver que tiene una precisión de microsegundos, es decir, sutilezas.
I.Segundo temporizador
void second_sleep(unsigned second){
struct timeval tv;
tv.tv_sec=segundos; /p>
tv.tv_usec=0;
for(i=0; ilt; 5; i){
printf("d\n",i) ;
//segundos_sueño(1);
//milisegundos_sueño(1500);
microsegundos_ sueño(1900000);
}
}
Nota: Aunque la estructura timeval especifica un nivel de resolución sutil, el soporte del kernel generalmente no es tan alto y muchos kernels Unix redondearán el valor del tiempo de espera a un múltiplo de 10 ms. Además, junto con el fenómeno del retraso en la programación del kernel, esto significa que después de que expire el tiempo del temporizador, el kernel todavía necesita algo de tiempo para programar la ejecución del proceso correspondiente.
Por lo tanto, la precisión del temporizador depende en última instancia de las velocidades independientes soportadas por el núcleo.