How can I implement timeout for read() when reading from a serial port (C/C++) How can I implement timeout for read() when reading from a serial port (C/C++) unix unix

How can I implement timeout for read() when reading from a serial port (C/C++)


Yes, use select(2). Pass in a file descriptor set containing just your fd in the read set and empty write/exception sets, and pass in an appropriate timeout. For example:

int fd = open(...);// Initialize file descriptor setsfd_set read_fds, write_fds, except_fds;FD_ZERO(&read_fds);FD_ZERO(&write_fds);FD_ZERO(&except_fds);FD_SET(fd, &read_fds);// Set timeout to 1.0 secondsstruct timeval timeout;timeout.tv_sec = 1;timeout.tv_usec = 0;// Wait for input to become ready or until the time out; the first parameter is// 1 more than the largest file descriptor in any of the setsif (select(fd + 1, &read_fds, &write_fds, &except_fds, &timeout) == 1){    // fd is ready for reading}else{    // timeout or error}


What is VMIN and VTIME used for?

If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before the read is satisfied. As TIME is zero, the timer is not used.

If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1 s). If TIME is exceeded, no character will be returned.

If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The read will be satisfied if MIN characters are received, or the time between two characters exceeds TIME. The timer is restarted every time a character is received and only becomes active after the first character has been received.

If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of characters currently available, or the number of characters requested will be returned. According to Antonino (see contributions), you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result.

Source : http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html


You can attempt capture signal to stop read operation. use alarm(1) before read, and if read function did not returned, alarm will send SIGALRM signal, then you can create signal processing function to capture this signal, like this:

#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <setjmp.h>static jmp_buf env_alarm;static void sig_alarm(int signo){    longjmp(env_alarm, 1);}int main(void){   int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);   char buf[1];   if (signal(SIGALRM, sig_alarm) == SIG_ERR)   {       exit(0);   }   if (setjmp(env_alarm) != 0)   {      close(fd);      printf("Timeout Or Error\n");      exit(0);   }   alarm(1);   int bytesRead = read(fd, buf, 1);   alarm(0);   close(fd);   return 0;}

But use select or poll or epoll will be better if your program is big.