Как реализовать тайм-аут в вызове функции чтения?

Я хочу использовать последовательный COM-порт для коммуникации, и я хочу реализовать тайм-аут каждый раз, когда я называю вызов функции чтения.

int filedesc = open( "dev/ttyS0", O_RDWR );

read( filedesc, buff, len );

Править:

Я использую Linux ОС. Как реализовать вызов функции выбора использования?

47
задан Alexis Wilke 24 April 2016 в 20:49
поделиться

4 ответа

select () принимает 5 параметров, сначала наивысший дескриптор файла + 1, затем fd_set для чтения, один для записи и один для исключений. Последний параметр - это структура timeval, используемая для тайм-аута. Он возвращает -1 при ошибке, 0 при тайм-ауте или количество файловых дескрипторов в установленных наборах.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>

int main(void)
{
  fd_set set;
  struct timeval timeout;
  int rv;
  char buff[100];
  int len = 100;
  int filedesc = open( "dev/ttyS0", O_RDWR );

  FD_ZERO(&set); /* clear the set */
  FD_SET(filedesc, &set); /* add our file descriptor to the set */

  timeout.tv_sec = 0;
  timeout.tv_usec = 10000;

  rv = select(filedesc + 1, &set, NULL, NULL, &timeout);
  if(rv == -1)
    perror("select"); /* an error accured */
  else if(rv == 0)
    printf("timeout"); /* a timeout occured */
  else
    read( filedesc, buff, len ); /* there was data to read */
}
77
ответ дан 26 November 2019 в 19:20
поделиться

В качестве альтернативы select () для В конкретном случае последовательного порта (терминала) вы можете использовать tcsetattr () , чтобы перевести файловый дескриптор в неканонический режим с тайм-аутом чтения.

Для этого снимите флаг ICANON и установите управляющий символ VTIME :

struct termios termios;

tcgetattr(filedesc, &termios);
termios.c_lflag &= ~ICANON; /* Set non-canonical mode */
termios.c_cc[VTIME] = 100; /* Set timeout of 10.0 seconds */
tcsetattr(filedesc, TCSANOW, &termios);

Примечание VTIME измеряется в десятых долях секунды, и что для него обычно используется тип unsigned char , что означает, что максимальный тайм-аут составляет 25,5 секунды.

39
ответ дан 26 November 2019 в 19:20
поделиться

Если вы установили, что сокет действительно работает в неблокирующем режиме, каждый вызов для чтения будет читать только данные, доступные в данный момент (если есть). Таким образом, это фактически эквивалентно немедленному таймауту.

Вы можете установить неблокирующий режим для сокета с помощью такой функции:

int setnonblock(int sock) {
   int flags;
   flags = fcntl(sock, F_GETFL, 0);
   if (-1 == flags)
      return -1;
   return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}

(Для получения дополнительной информации о чтении из неблокирующих сокетов см. читать страницу руководства)

8
ответ дан 26 November 2019 в 19:20
поделиться

Вы не говорите, что такое ОС, но если вы работаете под Linux, вы можете использовать вызов select. Он возвращается, если в файловом дескрипторе есть что читать, или вы можете настроить его так, чтобы он истекал по таймауту, если читать нечего. Код возврата указывает, какой именно.

4
ответ дан 26 November 2019 в 19:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: