2010-09-14 21 views

Respuesta

10

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); 
} 
+0

+1 Publicación agradable en el blog. – Tom

0

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.

+1

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. –

6

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. 
+0

+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. –

+0

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

+0

Correcto, no se cuenta como bloqueo, pero puede bloquearse durante un tiempo considerable. – nos

Cuestiones relacionadas