Temporización precisa e hibernación bajo Linux

  

La función de hibernación proporcionada en Linux es sleep (), pero solo proporciona hibernación en segundos. Esta hibernación es obviamente demasiado larga para algunos procesos, por lo tanto, ¿cómo puede hacerse más el proceso? ¿Resolución de tiempo de sueño pequeño?

Sé de dos maneras y las presentaré por separado a continuación.

El primer método es usar un temporizador. La función de temporizador proporcionada por Linux es:

int setitimer (int que, const struct itimerval * value, struct itimerval * ovalue); que especifica que Tipo de temporizador. Linux proporciona tres tipos de temporizadores:

TIMER_REAL: temporizador preciso, el tiempo de espera emitirá la señal SIGALRM; TIMER_VIRTUAL: temporizador virtual, solo procesará el tiempo, por lo que cambiará de acuerdo con el tiempo de ejecución del proceso, no se puede lograr una sincronización precisa, El tiempo de espera envía la señal SIGVTALRM; TIMER_PROF: Temporizador de sinopsis, cambiará de acuerdo con el tiempo del proceso y el tiempo del sistema, no se puede lograr la temporización precisa, la señal SIGPROF de tiempo de espera;

En el proceso debe capturarse el temporizador establecido. La señal, debido a que el proceso recibe una señal del tiempo de espera del temporizador, la acción predeterminada se termina.

valor es establecer el tiempo del temporizador, la estructura relevante es la siguiente:

struct itimerval {struct timeval it_interval; struct timeval it_value;}; struct timeval {long tv_sec; long tv_usec;}; it_interval intervalo especificado Time, it_value especifica el tiempo de sincronización inicial. Si solo se especifica it_value, se implementa una vez; si it_interval se especifica al mismo tiempo, después del tiempo de espera, el sistema reinicializará it_value a it_interval para implementar la repetición de tiempo; si ambos se borran, el temporizador se borrará.

tv_sec proporciona una precisión de segundo nivel, tv_usec proporciona una precisión de microsegundos, con un valor de primera, preste atención a 1s = 1000000us.

ovalue se usa para guardar el valor anterior, quedando como NULL.

Si duermes con un temporizador proporcionado por setitimer (), simplemente pausa la señal del temporizador de espera con pausa (). El segundo método es usar select () para proporcionar una sincronización e hibernación precisas:

int select (int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout); n se refiere a la supervisión El rango del descriptor de archivos, generalmente establecido en fd + 1, readfds, writefds y exceptfds para select () son conjuntos de descriptores de archivos de lectura, escritura y excepción, y el tiempo de espera es el tiempo de espera.

Las macros que se pueden usar para las operaciones de conjunto de descriptores de archivos son:

FD_CLR (int fd, fd_set * set); Clear fdFD_ISSET (int fd, fd_set * set); Test fd Establecer FD_SET (int fd, fd_set * set); Establecer fdFD_ZERO (fd_set * set); Borrar el conjunto de descriptores No necesitamos estas macros en este momento, porque no nos importa el estado del descriptor de archivos, nos importa seleccionar () Tiempo de espera Por lo tanto, debemos establecer readfds, writefds y exceptfds en NULL, solo especifique el tiempo de espera. En cuanto a n, no podemos preocuparnos, así que puedes establecerlo en cualquier valor no negativo. El código de implementación es el siguiente:

int usSleep (long us) {struct timeval tv; tv.tv_sec = 0; tv.tv_usec = us; return select (0, NULL, NULL, NULL, &tv);} Oh, ¿cómo, es muy simple?

Conclusión: setitimer () y select () pueden lograr una suspensión precisa del proceso. Este artículo brinda una breve introducción y una implementación sencilla basada en select (). No recomiendo usar setitimer porque uno de los sistemas Linux proporciona un número limitado de temporizadores (cada proceso puede tener como máximo 3 tipos diferentes de temporizadores), y setitimer () no tiene select () simple.

Editado el 12 de septiembre de 2008 ------------------------------------ -------------------------------

Gracias por los comentarios de 33 y ffff, ms y nosotros errores Ya corregido Como el hermano menor no es bueno para aprender, perdonaré el malentendido causado por todos. También agradezco sus comentarios y progresaremos juntos. He cambiado el título, el título original no es adecuado para el contenido actual, porque quiero agregar otras funciones de suspensión. Primero, como dice ffff, usleep () se puede usar para lograr dormir por debajo del segundo del proceso.

int usleep (unsigned long usec); Al igual que sleep (), vuelve cuando el proceso recibe una señal. Sin embargo, el manual de Linux dice que no devuelve el número de segundos sin dormir como en sleep (), sino que devuelve -1 y establece errno en EINTR. La implementación de uClibc es la siguiente:

int usleep (__useconds_t usec) {const struct timespec ts = {.tv_sec = (long int) (usec /1000000), .tv_nsec = (long int) (usec% 1000000) * 1000ul}; return (nanosleep (&ts, NULL));} Visible usleep () se implementa internamente mediante la función nanosleep (). A continuación, analizaremos la función nanosleep (). También he visto la siguiente implementación con select (), que también es compatible con el método que mencioné anteriormente.

int usleep (unsigned long usec) {static struct {/* `timeval '* /long tv_sec; /* seconds * /long tv_usec; ​​/* microsecs * /} delay; /* _select () timeout * /delay.tv_sec = usec /1000000L; delay.tv_usec = usec% 1000000L; return select (0, (long *) 0, (long *) 0, (long *) 0, &delay);} Luego volveremos Echa un vistazo a nanosleep (). Nanosleep () puede alcanzar el nivel de sueño de nanosegundos (1/1000 000 000), por lo que es más preciso que usleep (). Pero su CPU necesita al menos 1 GHz para admitir una resolución tan alta. El prototipo de nanosleep () es el siguiente:

int nanosleep (const struct timespec * rqtp, struct timespec * rmtp); el primer parámetro especifica el tiempo de suspensión y el segundo parámetro no devuelve el sueño cuando se interrumpe la señal. Una vez más, la estructura de timepec es la siguiente:

struct timespec {time_t tv_sec; /* seconds * /long tv_nsec; /* nanoseconds * /}; tv_sev se utiliza para especificar el número de segundos, tv_nsec se usa para especificar el número de nanosegundos 0-999 999 999), tenga en cuenta que, a diferencia de las otras funciones mencionadas anteriormente, nanosleep () se usa para ambos miembros de la estructura de especificaciones de tiempo, por lo que no puede especificar un valor mayor que 999 999 999 para tv_nsec. Regala tv_sec. Todas las funciones de sueño volverán cuando se encuentre la señal. Sleep () y alarm () devolverán el tiempo restante, mientras que usleep (), nanosleep () y select () devolverán -1.

Copyright © Conocimiento de Windows All Rights Reserved