Установите тайм-аут для чтения stdin

Есть ли способ таймаута чтения из stdin, чтобы программа не зависала слишком долго?

read(0, var, numberofbytes);

Ответ 1

Вы можете использовать ncurses, или если вы этого не хотите, вы можете использовать select, как описано в этом сообщение в блоге. В принципе, вы можете использовать select и указать таймаут. Если установлен stdin FD, вы можете безопасно читать и не блокировать. Если вы хотите получить дополнительную информацию о выборе, отметьте этот и, конечно, wikipedia. Это удобный вызов, чтобы узнать о нем.

РЕДАКТИРОВАТЬ: Я чувствую себя вынужденным предоставить код, так что вот он, прямо из сообщения в блоге с некоторыми комментариями.

// 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 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);
}

Ответ 2

Используйте выбор, опрос или любое другое средство мультиплексирования ввода-вывода. Все они принимают аргумент тайм-аута. Обратите внимание, что это не будет работать, если stdin является обычным файлом, но он будет, если stdin - это терминал /tty, socket, pipe.

например.

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.

Ответ 3

Вызовите alarm() или ualarm() перед вызовом read(). Это вызовет передачу сигнала SIGALRM в процесс, прерывая чтение() при условии, что вы не сказали O/S перезапустить системные вызовы после прерываний. Обязательно отмените сигнал тревоги, если read() возвращается нормально.