【问题标题】:C++ linux detect all serial portsC++ linux检测所有串口
【发布时间】:2013-03-11 15:46:29
【问题描述】:

有没有一种好方法可以检测所有连接在 linux 串口上的连接设备?我用 C++ 编程,但也欢迎其他示例。

您可以尝试打开每个端口,并在成功后将其添加到端口列表中,但这似乎不是一个很好的解决方案。

您可以进入开发总监,因为我的串行端口是 USB 端口,我可以检查哪些 ttyUSB.. 文件已制作。但这不适用于非 USB 串行端口,因为 tty0 到 tty63 的文件始终在此目录中。

我的例子:

std::string port;
int fd 
std::vector<std::string>> list;
for(int i = 0; i < 256; ++i)
{
    port.clear();
    port.append("/dev/ttyUSB");
    port.append(std::to_string(i));
    fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_DELAY);
    if(fd != -1)
    {
        list.push_back(port);
    }
}

谢谢!

【问题讨论】:

  • 串口通常命名为ttyS0等等。
  • 这给我一种XY问题的感觉,你的实际问题是X,而你认为​​解决方案是Y,所以你问Y。你为什么想知道关于串口系统?
  • 在其中一个端口上连接了一个 zigbee 设备。因为我想让它对用户友好,所以我想列出所有可能性,以便用户可以选择。通常,如果您插入您的 zigbee 设备,您应该会得到一个返回给您的端口号。 @Hasturkun 在我的情况下,因为我的串行设备使用 USB 连接,所以它被命名为 ttyUSB0。
  • @RoelStorms:我主要是回应关于非 USB 串口不工作的部分。
  • 理论上,如果你想要普通的串口,你可以对 /dev/ttyX 做同样的事情。但同样不是最好的方法。

标签: c++ ubuntu serial-port


【解决方案1】:

Linux 中枚举设备的标准方法是浏览/sys 文件系统。在这种情况下,您可以执行以下操作:

  1. 枚举/sys/class/tty中的所有文件
  2. 对于每个目录/sys/class/tty/foo,使用lstat() 检查/sys/class/tty/foo/device 是否存在。
    • 如果它不存在,那么您正在处理某种虚拟 tty 设备(虚拟控制台端口、ptmx 等...),您可以丢弃它。
    • 如果存在则保留串口foo

您应该得到一个实际串行端口的列表。

【讨论】:

  • 我通过这种机制获得了 32 台设备。 2 有效。你需要检查它没有指向serial8250,它实际上只是驱动程序
  • 在我的几个系统上,我有真正有效的串行端口,其中device 符号链接指向serial8250...我不知道你为什么得到这么多无效的。
  • 32 来自内核配置值CONFIG_SERIAL_8250_RUNTIME_UARTS,我认为它支持的不仅仅是默认的32(这是一个x64 3.2 内核)。
  • 如果我只是检查 sys/class/tty/ttyS.. 那么我会在所有这些文件夹中找到一个设备文件夹。所以这可能就是 Petesh 达到 32 的原因,因为 ttyS 从 0 变为 31。
  • @Lotharyx 您可以使用udevadm info /sys/class/tty/&lt;device-name&gt;,它将为您提供DEVNAME 以及可能为其创建的任何符号链接。
【解决方案2】:

鉴于自从回答这个问题以来已经过去了很多年,我正在添加这个答案。这个答案适用于更高版本的linux。它还使用了 c++17 中引入的新的std::filesystemstd::filesystem 在早期版本的 c++ 中可以通过 boost 或命名空间std::experimental::filesystem 使用(使用#include &lt;experimental/filesystem&gt;)。如果使用 boost 你必须包含编译组件system

此示例还计算出符号链接指向的位置并返回它的规范名称。

#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>

using std::cout;
namespace fs = boost::filesystem;

std::vector<std::string> get_available_ports() {
    std::vector<std::string> port_names;

    fs::path p("/dev/serial/by-id");
    try {
      if (!exists(p)) {
        throw std::runtime_error(p.generic_string() + " does not exist");
      } else {
        for (fs::directory_entry &de : fs::directory_iterator(p)) {
          if (is_symlink(de.symlink_status())) {
            fs::path symlink_points_at = read_symlink(de);
            fs::path canonical_path = fs::canonical(symlink_points_at, p);
            port_names.push_back(canonical_path.generic_string());
          }
        }
      }
    } catch (const fs::filesystem_error &ex) {
      cout << ex.what() << '\n';
      throw ex;
    }
    std::sort(port_names.begin(), port_names.end());
    return port_names;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    相关资源
    最近更新 更多