如何在Linux中使用libudev以编程方式列出USB大容量存储设备?

jsa*_*aji 5 c c++ linux user-interface linux-kernel

我正在用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);
Run Code Online (Sandbox Code Playgroud)

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

gav*_*avv 11

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

  • SUBSYSTEM =="scsi",DEVTYPE =="scsi_device"
  • 子设备与SUBSYSTEM存在=="阻止"
  • 子设备与SUBSYSTEM =="scsi_disk"一起存在
  • 父设备存在SUBSYSTEM =="usb",DEVTYPE =="usb_device"

这是示例程序(也可以在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;
}
Run Code Online (Sandbox Code Playgroud)

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

block = /dev/sdb, usb = 0bc2:ab20, scsi = Seagate
Run Code Online (Sandbox Code Playgroud)