udev

udev는 /dev 노드를 동적으로 생성하고 이를 위한 규칙을 관리하는 시스템 서비스이다. libudev(-ludev)를 사용하여 udev 객체에 접근하고, udev 이벤트를 모니터링 할 수 있다.

Examples

Enumerate block devices

#include <libudev.h>

int main(int argc, char* argv[]) {
  struct udev* udev;
  struct udev_enumerate* enumerate;
  struct udev_list_entry* devices;
  struct udev_device* dev;

  // Create the udev object
  udev = udev_new();
  if (!udev) {
    ESF_LOG_ERROR(kTag, "Cannot create udev");
  }

  // Create the enumerator object
  enumerate = udev_enumerate_new(udev);

  // Create a list of the devices
  udev_enumerate_add_match_subsystem(enumerate, "block");
  udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition");
  udev_enumerate_scan_devices(enumerate);
  devices = udev_enumerate_get_list_entry(enumerate);

  // For each entry enumerated, add to device_list
  struct udev_list_entry* entry;
  udev_list_entry_foreach(entry, devices) {
    const char* path;
    const char* node;

    path = udev_list_entry_get_name(entry);
    dev = udev_device_new_from_syspath(udev, path);
    node = udev_device_get_devnode(dev);

    // To do something for each devices

    udev_device_unref(dev);
  }

  // Free the enumerator object
  udev_enumerate_unref(enumerate);

  // Free the udev object
  udev_unref(udev);
  
  return 0;
}

Monitor block devices


#include <libudev.h>

int main(int argc, char* argv[]) {
  struct udev* udev;
  struct udev_device* dev;
  struct udev_monitor* mon;
  int fd;

  // Create the udev object
  udev = udev_new();
  if (!udev) {
    ESF_LOG_ERROR(kTag, "Cannot create udev");
  }
  
  // Set up a monitor to monitor devices
  mon = udev_monitor_new_from_netlink(udev, "udev");
  udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "partition");
  udev_monitor_enable_receiving(mon);

  // Get the file descriptor for the monitor
  fd = udev_monitor_get_fd(mon);

  fd_set fds;
  int ret;
  struct timeval timeout = {0};

  while (self->monitor_running_) {
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    ret = select(fd + 1, &fds, NULL, NULL, &timeout); // change to blocking IO
    if (ret > 0 && FD_ISSET(fd, &fds)) {
      dev = udev_monitor_receive_device(mon);
      if (dev) {
        const char* action = udev_device_get_action(dev);
        const char* node = udev_device_get_devnode(dev);

        if (strcmp("add", action) == 0) {
          // To do somthing for device added
        } else if (strcmp("remove", action) == 0) {
          // To do somthing for device removed
        }
        udev_device_unref(dev);
      }
    }
  }

  // Free the udev object
  udev_unref(udev);
  
  return 0;
}

Get mounted directory from block dev node

#include <mntent.h>

int main(ing argc, char* argv[]) {
  FILE* file;
  struct mntent* ent;

  file = setmntent("/etc/mtab", "r");
  if (file == nullptr) {
    std::cerr << "Cannot open /etc/mtab" << std::endl
  }

  // Find mounted directory of device node
  while (nullptr != (ent = getmntent(file))) {
    if (strcmp(ent->mnt_fsname, dev_node) == 0) {
      std::cout << "Dev " << dev_node << " Mounted to: " << ent->mnt_dir << std::endl;
      break;
    }
  }

  endmntent(file);
  return 0;
}

참고

태그:

카테고리:

업데이트: