5

有没有一种很好的方法来检测连接在 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);
    }
}

谢谢!

4

2 回答 2

9

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

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

您应该留下一个实际串行端口的列表。

于 2013-03-11T16:24:35.167 回答
1

鉴于自从回答这个问题以来已经过去了很多年,我正在添加这个答案。这个答案适用于更高版本的linux。它还使用了std::filesystemc++17 中引入的新功能。 std::filesystem在早期版本的 c++ 中可以通过 boost 或命名空间std::experimental::filesystem(use #include <experimental/filesystem>) 使用。如果使用 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;
}
于 2021-01-17T18:23:26.227 回答