You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用libudev通过PID和VID获取设备的/dev路径

解答
  • 该需求完全可实现。
  • 你当前无法获取目标/dev路径的核心原因:你枚举的是usb子系统下类型为usb_device的USB总线原生设备节点,这类节点对应的设备路径是/dev/bus/usb/xxx/xxx格式的总线访问路径,不是USB设备绑定功能驱动后生成的ttyUSB、hidraw这类功能设备节点,自然拿不到你要的串口路径。

实现方法

你可以任选以下两种方式实现:

方法1:在现有匹配逻辑基础上遍历子设备找功能节点

找到匹配VID/PID的USB设备对象后,遍历它的所有子设备,筛选对应功能子系统的节点,调用接口取dev路径即可。以USB转串口设备(对应tty子系统,生成ttyUSBx/ttyACMx节点)为例,在你代码的匹配判断分支中添加如下逻辑:

if (vendor_id == VID && product_id == PID) {
    struct udev_device *child = nullptr;
    const char* target_path = nullptr;
    // 遍历当前USB设备的所有子设备
    udev_device_foreach_child(child, raw_dev) {
        const char *subsys = udev_device_get_subsystem(child);
        // 匹配tty子系统,若你用的是HID/存储类设备,替换为对应子系统名即可
        if (subsys && strcmp(subsys, "tty") == 0) {
            target_path = udev_device_get_devnode(child);
            break;
        }
    }
    // target_path即为目标路径,例如/dev/ttyUSB0
    if (target_path) {
        printf("Found target device: %s\n", target_path);
    }
}

注意:如果你的设备不是串口类设备,需要将子系统匹配规则替换为对应类型:比如HID设备匹配hidraw子系统拿到/dev/hidrawx路径,USB存储设备匹配block子系统拿到/dev/sdx路径。

方法2:直接枚举目标功能子系统匹配PID/VID

这种方式代码更简洁,不需要遍历子设备:直接枚举你需要的功能子系统(比如tty)的设备,这类设备会自动继承父USB设备的idVendor、idProduct属性,匹配成功后直接取devnode即可:

ud = udev_new();
struct udev_enumerate *enumerate = udev_enumerate_new(ud);
// 直接匹配tty子系统,不需要匹配usb子系统和usb_device类型
udev_enumerate_add_match_subsystem(enumerate, "tty");
udev_enumerate_scan_devices(enumerate);

struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *dev_list_entry;
udev_list_entry_foreach(dev_list_entry, devices)
{
    const char *sysfs_path = udev_list_entry_get_name(dev_list_entry);
    struct udev_device *dev = udev_device_new_from_syspath(ud, sysfs_path);

    uint16_t vendor_id;
    uint16_t product_id;
    // 直接从tty设备读取继承的VID/PID属性,判断读取返回值避免无效值
    if (udev_get_sysattr_u16_base16(dev, "idVendor", &vendor_id) == 0 &&
        udev_get_sysattr_u16_base16(dev, "idProduct", &product_id) == 0 &&
        vendor_id == VID && product_id == PID) {
        // 直接获取dev路径,不需要遍历子设备
        const char* target_path = udev_device_get_devnode(dev);
        printf("Found target device: %s\n", target_path);
    }
    udev_device_unref(dev);
}
// 用完后释放udev对象,避免内存泄漏
udev_enumerate_unref(enumerate);
udev_unref(ud);

其他注意事项

  • 所有udev_*创建的对象用完后必须调用对应的_unref接口释放,避免内存泄漏。
  • 如果设备存在多个接口对应多个功能节点(比如USB转多串口设备),遍历子设备时会拿到多个/dev/ttyUSBx路径,可根据接口号、驱动名等属性进一步筛选你需要的节点。

内容的提问来源于stack exchange,提问作者dan123123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:03:29