¿Hay alguna manera de esperar el tiempo de espera de una lectura de stdin para que el programa no se cuelgue demasiado tiempo?Establecer un tiempo de espera para leer stdin
read(0, var, numberofbytes);
¿Hay alguna manera de esperar el tiempo de espera de una lectura de stdin para que el programa no se cuelgue demasiado tiempo?Establecer un tiempo de espera para leer stdin
read(0, var, numberofbytes);
Puede utilizar ncurses o si no desea, puede utilizar select como se describe en este blog post. Básicamente, puede usar select
y especificar el tiempo de espera. Si está configurado el stdin FD, entonces puede leerlo de forma segura y no se bloqueará. Si desea más información sobre seleccionar, marque this y por supuesto wikipedia. Es una llamada útil para saber.
EDIT: Me siento obligado a proporcionar el código, así que aquí está, directamente desde la entrada del blog con algunos comentarios.
// if != 0, then there is data to be read on stdin
int kbhit()
{
// timeout structure passed into select
struct timeval tv;
// fd_set passed into select
fd_set fds;
// Set up the timeout. here we can wait for 1 second
tv.tv_sec = 1;
tv.tv_usec = 0;
// Zero out the fd_set - make sure it's pristine
FD_ZERO(&fds);
// Set the FD that we want to read
FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
// select takes the last file descriptor value + 1 in the fdset to check,
// the fdset for reads, writes, and errors. We are only passing in reads.
// the last parameter is the timeout. select will return if an FD is ready or
// the timeout has occurred
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
// return 0 if STDIN is not ready to be read.
return FD_ISSET(STDIN_FILENO, &fds);
}
llamada alarm()
o ualarm()
antes de llamar read()
. Esto causará que se entregue una señal SIGALRM
al proceso, interrumpiendo la lectura(), provista con que no le ha indicado al O/S que reinicie las llamadas al sistema después de las interrupciones. Asegúrese de cancelar la alarma si el read()
regresa normalmente.
El colgante predeterminado para 'SIGALRM' finaliza el proceso, por lo que deberá instalar un manejador de señal. Y en un sistema operativo sano, las señales no interrumpen las llamadas de sistema por defecto, por lo que necesitarás usar 'sigaction' en lugar de' signal' para asegurarte de que lo hagan. –
Utilice seleccionar, sondear o cualquier otra instalación de multiplexación IO. Todos toman un argumento de tiempo de espera. Tenga en cuenta que esto no funcionará si stdin es un archivo normal, pero lo hará si stdin es un terminal/tty, socket, pipe.
p. Ej.
fd_set selectset;
struct timeval timeout = {10,0}; //timeout of 10 secs.
int ret;
FD_ZERO(&selectset);
FD_SET(0,&selectset);
ret = select(1,&selectset,NULL,NULL,&timeout);
if(ret == 0)
//timeout
else if(ret == -1)
//error
else
// stdin has data, read it
// (we know stdin is readable, since we only asked for read events
//and stdin is the only fd in our select set.
+1 para la respuesta que no depende de las señales y de interferir con el estado global del proceso, que puede no ser apropiado/permisible desde el código de la biblioteca. –
Bueno, "funcionará" para un archivo normal, ya que siempre dirá que leer no se bloqueará, lo cual es cierto (esperar que un disco o sistema de archivos de red suministre datos no cuenta como "bloqueo") . – caf
Correcto, no se cuenta como bloqueo, pero puede bloquearse durante un tiempo considerable. – nos
+1 Publicación agradable en el blog. – Tom