sysfs的了解及libudev的浅析 (三) —— 第一层到第二层

      两个重点中的第一个

UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
{
    if (udev_enumerate == NULL)
         return -EINVAL;
    /* efficiently lookup tags only, we maintain a reverse-index */
    if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL)
        return scan_devices_tags(udev_enumerate);
    /* walk the subtree of one parent device only */
    if (udev_enumerate->parent_match != NULL)
        return scan_devices_children(udev_enumerate);
    /* scan devices of all subsystems */
    return scan_devices_all(udev_enumerate);
}

      初始化时tags_match_list, true,第二个return 可能执行的,第四个return是扫描所有的。我们一般没有设置要匹配的tag,所以第二个return应该是跳过的。第三个,有parent的时候才会去扫描children。所以这里应该是执行第四个。我们姑且认为是这样。

static int scan_devices_all(struct udev_enumerate *udev_enumerate)
{
struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
char base[UTIL_PATH_SIZE];
struct stat statbuf;

util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL);
if (stat(base, &statbuf) == 0) {
/* we have /subsystem/, forget all the old stuff */
dbg(udev, "searching '/subsystem/*/devices/*' dir\n");
scan_dir(udev_enumerate, "subsystem", "devices", NULL);
} else {
dbg(udev, "searching '/bus/*/devices/*' dir\n");
scan_dir(udev_enumerate, "bus", "devices", NULL);
dbg(udev, "searching '/class/*' dir\n");
scan_dir(udev_enumerate, "class", NULL, NULL);
}
return 0;
}

      sysfs下/subsystem一般不会有,所以会去sysfs下/bus/*/devices/*、/class/*下扫描所有设备。

static int scan_dir(struct udev_enumerate *udev_enumerate, 

                            const char *basedir, const char *subdir, const char *subsystem)
{
struct udev *udev = udev_enumerate_get_udev(udev_enumerate);


char path[UTIL_PATH_SIZE];
DIR *dir;
struct dirent *dent;


util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL);
dir = opendir(path);
if (dir == NULL)
return -1;
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
if (dent->d_name[0] == '.')
continue;
if (!match_subsystem(udev_enumerate, subsystem != NULL ? subsystem : dent->d_name))
continue;
scan_dir_and_add_devices(udev_enumerate, basedir, dent->d_name, subdir);
}
closedir(dir);
return 0;
}

      sysfs下/bus/、/class/都是有的。readdir()。第四个参数是NULL,所以比较d_name和之前设置的要匹配的subsystem。

      bus,总线,有很多,如

[root@localhost bus]# ls
acpi         clocksource  event_source  i2c           mdio_bus  pci          pcmcia    pnp   serio  usb-serial  xen
clockevents  cpu          hid           machinecheck  node      pci_express  platform  scsi  usb    workqueue   xen-backend

      class下面也有很多,

[root@localhost class]# ls
ata_device  bdi        cpuid  graphics     ieee80211  mem   pci_bus        rfkill       scsi_generic   thermal  vtconsole
ata_link    block      dma    hidraw       input      misc  pcmcia_socket  rtc          scsi_host      tty      watchdog
ata_port    bluetooth  dmi    hwmon        leds       msr   power_supply   scsi_device  spi_host       usbmon
backlight   bsg        drm    i2c-adapter  mdio_bus   net   raw            scsi_disk    spi_transport  vc

      键鼠、触摸,属于输入类,所以subsystem选择input来匹配,即找到/class/input,找到了,之后就是扫描它下面的并添加设备。注意传参的内容,因为匹配到的是class下的,所以scan_dir(udev_enumerate, "class", NULL, NULL); 传 class、input、NULL


static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate,
   const char *basedir, const char *subdir1, const char *subdir2)
{
struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
char path[UTIL_PATH_SIZE];
size_t l;
char *s;
DIR *dir;
struct dirent *dent;

s = path;
l = util_strpcpyl(&s, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL);
if (subdir1 != NULL)
l = util_strpcpyl(&s, l, "/", subdir1, NULL);
if (subdir2 != NULL)
util_strpcpyl(&s, l, "/", subdir2, NULL);
dir = opendir(path);
if (dir == NULL)
return -ENOENT;
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
char syspath[UTIL_PATH_SIZE];
struct udev_device *dev;

if (dent->d_name[0] == '.')
continue;

if (!match_sysname(udev_enumerate, dent->d_name))
continue;

util_strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL);
dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
if (dev == NULL)
continue;

if (udev_enumerate->match_is_initialized) {
/*
* All devices with a device node or network interfaces
* possibly need udev to adjust the device node permission
* or context, or rename the interface before it can be
* reliably used from other processes.
*
* For now, we can only check these types of devices, we
* might not store a database, and have no way to find out
* for all other types of devices.
*/
if (!udev_device_get_is_initialized(dev) &&
   (major(udev_device_get_devnum(dev)) > 0 || udev_device_get_ifindex(dev) > 0))
goto nomatch;
}
if (!match_parent(udev_enumerate, dev))
goto nomatch;
if (!match_tag(udev_enumerate, dev))
goto nomatch;
if (!match_property(udev_enumerate, dev))
goto nomatch;
if (!match_sysattr(udev_enumerate, dev))
goto nomatch;

syspath_add(udev_enumerate, udev_device_get_syspath(dev));
nomatch:
udev_device_unref(dev);
}
closedir(dir);
return 0;
}

      /class/input下readdir()。

[root@localhost input]# ls
event0  event1  event2  event3  input0  input1  input2  input3  mice  mouse0  mouse1

这是PC linux系统下/sys/class/input下的内容,这就是我们要找的已存在的键鼠、触摸设备。但是怎么区分呢?

     初始化是sysname_match_list, true,如果不匹配就继续了,说明是要匹配的,匹配什么呢?再说。

     现在关注的是怎么区分出来。取event0

       dev = udev_device_new_from_syspath( , /sys/class/input/event0)

       syspath_add(, udev_device_get_syspath(dev));

      这就是它的精髓了。也就是第二个重点。

你可能感兴趣的:(sysfs的了解及libudev的浅析 (三) —— 第一层到第二层)