【问题标题】:how to list USB mass storage devices programatically using libudev in Linux?如何在 Linux 中使用 libudev 以编程方式列出 USB 大容量存储设备?
【发布时间】:2016-07-13 05:41:47
【问题描述】:

我正在做一个在 linux 中使用大容量存储设备的项目。我正在尝试编写一个应用程序,它将列出所有连接的 USB 大容量存储设备,并在插入新的大容量存储设备时发出通知。我为此目的使用 libudev。我使用了 "http://www.signal11.us/oss/udev/" 中的代码。我这里做了修改

  /* Create a list of the devices in the 'block' subsystem. */
  enumerate = udev_enumerate_new(udev);
  udev_enumerate_add_match_subsystem(enumerate, "block");
  udev_enumerate_scan_devices(enumerate);
  devices = udev_enumerate_get_list_entry(enumerate);

现在的问题是它列出了所有的块设备。我只想要 USB 大容量存储设备。如何获取这个列表。还有一个问题是如何使用libudev获取USB存储设备的标签。

【问题讨论】:

  • 查看父设备。
  • @CL。你能解释一下吗..我使用了signal11.us/oss/udev中的代码
  • 您是否尝试在该页面中搜索“父母”?

标签: c++ c linux user-interface linux-kernel


【解决方案1】:

一种解决方案是使用以下标准匹配设备:

  • SUBSYSTEM == "scsi", DEVTYPE == "scsi_device"
  • 子设备存在,SUBSYSTEM == "block"
  • 子设备存在 SUBSYSTEM == "scsi_disk"
  • 父设备存在 SUBSYSTEM == "usb", DEVTYPE == "usb_device"

这里是示例程序(也可以使用on github):

#include <libudev.h>
#include <stdio.h>

static struct udev_device*
get_child(
     struct udev* udev, struct udev_device* parent, const char* subsystem)
{
  struct udev_device* child = NULL;
  struct udev_enumerate *enumerate = udev_enumerate_new(udev);

  udev_enumerate_add_match_parent(enumerate, parent);
  udev_enumerate_add_match_subsystem(enumerate, subsystem);
  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
  struct udev_list_entry *entry;

  udev_list_entry_foreach(entry, devices) {
    const char *path = udev_list_entry_get_name(entry);
    child = udev_device_new_from_syspath(udev, path);
    break;
  }

  udev_enumerate_unref(enumerate);
  return child;
}

static void enumerate_usb_mass_storage(struct udev* udev)
{
  struct udev_enumerate* enumerate = udev_enumerate_new(udev);

  udev_enumerate_add_match_subsystem(enumerate, "scsi");
  udev_enumerate_add_match_property(enumerate, "DEVTYPE", "scsi_device");
  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
  struct udev_list_entry *entry;

  udev_list_entry_foreach(entry, devices) {
    const char* path = udev_list_entry_get_name(entry);
    struct udev_device* scsi = udev_device_new_from_syspath(udev, path);

    struct udev_device* block = get_child(udev, scsi, "block");
    struct udev_device* scsi_disk = get_child(udev, scsi, "scsi_disk");

    struct udev_device* usb
      = udev_device_get_parent_with_subsystem_devtype(
          scsi, "usb", "usb_device");

    if (block && scsi_disk && usb) {
        printf("block = %s, usb = %s:%s, scsi = %s\n",
          udev_device_get_devnode(block),
          udev_device_get_sysattr_value(usb, "idVendor"),
          udev_device_get_sysattr_value(usb, "idProduct"),
          udev_device_get_sysattr_value(scsi, "vendor"));
    }

    if (block)
      udev_device_unref(block);

    if (scsi_disk)
      udev_device_unref(scsi_disk);

    udev_device_unref(scsi);
  }

  udev_enumerate_unref(enumerate);
}

int main()
{
  struct udev* udev = udev_new();

  enumerate_usb_mass_storage(udev);

  udev_unref(udev);
  return 0;
}

它是我的外部磁盘的输出:

block = /dev/sdb, usb = 0bc2:ab20, scsi = Seagate

【讨论】:

  • 我收到以下错误:“udev_enumerate_add_match_parent' 未在此范围内声明”。
  • @RaviBhushan,我猜你有旧的 libudev。该函数最早出现在 udev-174 中。
  • 我一使用udev_enumerate_add_match_parent valgrind 就抱怨内存泄漏。
  • @Th.Thielemann,无法使用此 sn-p 进行复制。你能发布你的代码吗?
猜你喜欢
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多