09-07-07 12:24 PM
I'm writing an application that needs to communicate with a device
attached to a serial port. For reading data, I want to be able to
specify a total timeout value.
The code I'm using now (see below) assumes that select() modifies the
timeout structure to indicate the remaining time. This works on my linux
system, but according to the man pages, this is not portable. So I want
to recalculate the timeout myself. My first idea was to use the
gettimeofday() function. But that function does calculate the elapsed
real time, not the system time spend in the select call. This results in
a different behavior when the select call is interrupted by a signal
(which is detected as in the helper function myselect() below). Is there
a better way to recalculate the timeout?
int g_timeout = 1000O; // Timeout in milliseconds
int serial_read (int fd, void* buffer, unsigned int count)
{
// Initialize the file descriptor set.
fd_set fds;
FD_ZERO (&fds);
FD_SET (fd, &fds);
// Initialize the timeout.
struct timeval tv
tv.tv_sec = (g_timeout / 1000);
tv.tv_usec = (g_timeout % 1000) * 1000;
int nbytes = 0;
while (nbytes < count) {
// See if there is data available.
int rc = select (fd + 1, &fds, NULL, NULL, &tv);
// TODO: Recalculate timeout here!
if (rc < 0) {
return -1; // Error during select call.
} else if (rc == 0)
break; // Timeout.
// Read the available data.
int n = read (fd, buffer + nbytes, count - nbytes);
if (n < 0) {
return -1; // Error during read call.
} else if (n == 0)
break; // EOF reached.
// Increase the number of bytes read.
nbytes += n;
}
// Return the number of bytes read.
return nbytes;
}
int myread (int fd, void* buffer, unsigned int count)
{
int rc = 0;
do {
rc = read (fd, buffer, count);
} while (rc < 0 && errno == EINTR)
return rc;
}
int myselect (int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
int rc = 0;
do {
rc = select (nfds, readfds, writefds, exceptfds, timeout);
// TODO: Recalculate timeout here!
} while (rc < 0 && errno == EINTR)
return rc;
}
[ Post a follow-up to this message ]
|