【问题标题】:Detecting if a character device has disconnected in Linux in with termios api (c++)使用 termios api (c++) 在 Linux 中检测字符设备是否已断开连接
【发布时间】: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


【解决方案1】:

首先值得一提的是,serial-usb 的行为如下:

在 USB 设备上调用拔出断开连接

@disconnect:接口不再可访问时调用,通常 因为它的设备已经(或正在)断开连接或 正在卸载驱动模块。

在我们的例子中是 usb_serial_disconnect(struct usb_interface *interface)

调用usb_serial_console_disconnect(serial),调用tty_hangup ...等等。

您可以从这里开始关注链: http://lxr.free-electrons.com/source/drivers/usb/serial/usb-serial.c#L1091

简而言之,这导致以下经典方式:

pselect 表示文件描述符已准备就绪,并且 ioctl(fd, FIONREAD, &len) 返回零 len。

就是你拔掉了设备。

总结(源自您的代码):

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
    int ready = select(tty_fd + 1, &rfds, NULL, NULL, NULL);

    if(ready && FD_ISSET(tty_fd, &rfds)) {
      size_t len = 0;
      ioctl(tty_fd, FIONREAD, &len);
      errsv = errno;

      if(len == 0)
      {
         printf("prog_name: zero read from the device: %s.", strerror(errsv));
         /* close fd and cleanup or reconnect etc...*/
         exit(EXIT_FAILURE);
      }

      // 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();
    }
}

很遗憾您没有说明您使用的是哪种设备。

如果您的设备能够进行 RTS/CTS 流控制,也可以检测换行符。

【讨论】:

  • 您好,感谢您的详细评论!该设备是连接到 Raspberry Pi 的 FTDI 芯片。 Raspian Jessie,如果发行版很重要。稍后我会尝试这个并更新它的结果。
  • Np,实际上零读取来自用虚拟处理程序替换默认操作处理程序,读取时返回零。它与套接字的行为几乎相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 2017-03-16
相关资源
最近更新 更多