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;
}