利布代夫如何将轮询与文件描述符一起使用

libudev how to use poll with the file descriptor

本文关键字:描述 文件 一起 布代夫      更新时间:2023-10-16

所以,我有一个应用程序,我想在 Linux 上收到热插拔事件的通知。自然,我查看了libudev及其API。我还找到了一个关于如何在 libudev 中使用 select() 的有用教程。按照教程并浏览 API,我想出了这个示例程序,该程序等待热插拔事件,然后输出有关刚刚添加或删除的设备的一些基本信息。

#include <poll.h>
#include <libudev.h>
#include <stdexcept>
#include <iostream>
udev* hotplug;
udev_monitor* hotplug_monitor;
void init()
{
  // create the udev object
  hotplug = udev_new();
  if(!this->hotplug)
  {
    throw std::runtime_error("cannot create udev object");
  }
  // create the udev monitor
  hotplug_monitor = udev_monitor_new_from_netlink(hotplug, "udev");
  // start receiving hotplug events
  udev_monitor_enable_receiving(hotplug_monitor);
}
void deinit()
{
  // destroy the udev monitor
  udev_monitor_unref(hotplug_monitor);
  // destroy the udev object
  udev_unref(hotplug);
}
void run()
{
  // create the poll item
  pollfd items[1];
  items[0].fd = udev_monitor_get_fd(hotplug_monitor);
  items[0].events = POLLIN;
  items[0].revents = 0;
  // while there are hotplug events to process
  while(poll(items, 1, 50) > 0)
  {
    // XXX
    std::cout << "hotplug[ " << items[0].revents << " ]" << std::endl;
    // receive the relevant device
    udev_device* dev = udev_monitor_receive_device(hotplug_monitor);
    if(!dev)
    {
      // error receiving device, skip it
      continue;
    }
    // XXX
    std::cout << "hotplug[" << udev_device_get_action(dev) << "] ";
    std::cout << udev_device_get_devnode(dev) << ",";
    std::cout << udev_device_get_subsystem(dev) << ",";
    std::cout << udev_device_get_devtype(dev) << std::endl;
    // destroy the relevant device
    udev_device_unref(dev);
    // XXX
    std::cout << "done" << std::endl;
    // clear the revents
    items[0].revents = 0;
  }
}
int main(int args, char* argv[])
{
  init();
  while(true)
  {
    run();
  }
  deinit();
}

好吧,它不起作用。这是我插入 USB 鼠标时得到的输出。

hotplug[ 1 ]
hotplug[add] /dev/bus/usb/008/002,usb,usb_device
done
hotplug[ 1 ]
hotplug[add]

此时程序冻结,我必须使用 Ctrl-C 停止它。我做错了什么?

程序实际上并没有停止;它继续运行,但是当你尝试打印一个 NULL 字符串时,std::cout 会搞砸(并非所有事件都有所有属性)。解决方法是使三个打印(devnode,子系统,devtype)有条件。