【发布时间】:2016-03-14 05:26:33
【问题描述】:
我在 Linux 中使用 termios api 与串行设备进行通信。我正在尝试检测设备是否已断开连接,以便在超时后尝试重新连接。我有以下示例代码:
while(1)
{
FD_ZERO(&rfds);
FD_SET(tty_fd, &rfds);
// have tried checking fcntl(tty_fd, F_GETFL); too
// Blocking call to wait until we have data
select(tty_fd+1, &rfds, NULL, NULL, NULL);
// While we have data, collect it
while (read(tty_fd, &c, 1)>0 && bytesRead++<200)
{
serialBuffer.push_back(c);
}
bytesRead = 0;
// Try to parse it
BufferParse();
}
在 ttyUSB 设备物理断开后,我实际上没有看到 select() 或 fcntl 返回错误值 (-1)。当然,我可以检查 /dev/ 中的文件是否存在,但我希望有一个更优雅的解决方案。
不胜感激,谢谢!
【问题讨论】:
-
使用 USB 适配器,可能有两个级别的断开连接。将设备连接到串行端口后,该设备无法再进行通信。 RS232 链路本身可能断开。 DSR/DTR 信号通常用于确定本地连接。图中还有 USB,USB 适配器可能会与主机断开连接。因此,您需要澄清您要检测的内容。读取数据将来自连接的串行设备,而不是串行端口或 USB 适配器。如果设备是调制解调器,那么您有另一个连接链接。
-
在这种情况下,我专门讨论的是 USB 转串口设备与主机断开连接。
-
您可以使用 libudev 通过文件描述符来观察设备事件:signal11.us/oss/udev
-
我认为您还应该为
select()设置exceptfds(参数#4)。只要套接字本身没有关闭(并且它只能被您的程序关闭),select()就不会得到 -1。您可能应该也收到readfds的指示(在exceptfds之外),并且在尝试read()时,您也应该在那里收到错误(EIO 或类似的)。 -
正如锯末所发布的,断开连接的类型有很多种。过去我有一个案例,我无法确定串行链路是否由于电缆损坏等简单原因而丢失。我最终使用串行心跳并在超时线程上检测到它。这是更安全的解决方案,因为在某些情况下 termios 可能不会发出信号。
标签: c++ linux serial-port termios