开发者

Linux serial port woes

开发者 https://www.devze.com 2023-04-12 02:47 出处:网络
I am writing code to talk to another device over serial in linux I want non-blocking with timeout even if 0 characters arrive. The termios struct allows you to set VTIME and VMIN, but if VMIN is larg

I am writing code to talk to another device over serial in linux

I want non-blocking with timeout even if 0 characters arrive. The termios struct allows you to set VTIME and VMIN, but if VMIN is larger than 0, and if 0 characters are returned, the read call will block forever...WTF, why. This does not seem to cover the case where the other device开发者_如何转开发 goes down for a short period of time and now my application is blocked on a read call. This seems like a critical behavior to neglect. I really do not want to implement my own timeouts.

Write command
Read block timeout of around .3s(if 0 characters, still wait max of .3s)


If you want read to return with no data after a timeout you can set MIN == 0 and TIME > 0. From tcsetattr(3):

MIN == 0; TIME > 0: TIME specifies the limit for a timer in tenths of a second. The timer is started when read(2) is called. read(2) returns either when at least one byte of data is available, or when the timer expires. If the timer expires without any input becoming available, read(2) returns 0.

This mode can be used to build higher level communication functions which you must implement anyway in order to deal with partial reads (i.e. if the other end crashes in the middle of a "packet"), wrong packets, split packets and so on. That's all stuff which a simple read cannot do for you.


Take a look at select. It waits until data is ready to read (but doesn't actually read anything). From the man page:

timeout is an upper bound on the amount of time elapsed before select() returns. It may be zero, causing select() to return immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.

The code would look something like:

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 300000;

fd_set infds;
FD_ZERO(&infds);
FD_SET(fd, &infds);

// Assume fd is the file descriptor for the serial device
if (select(fd + 1, &infds, NULL, NULL, &tv) > 0)
{
    // The read will not block now
    // Assume buffer and size are declared and set appropriately
    amountRead = read(fd, buffer, size);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号