Skip to content

Utils_UdevMonitor

SweerItTer edited this page Feb 1, 2026 · 3 revisions

UdevMonitor API 文档

概述

UdevMonitor 是 utilsCore Utils 模块的核心类,提供 Linux udev 事件监听功能,支持设备热插拔监控。

职责

  • 监听 Linux udev 事件
  • 支持注册多个 (subsystem, actions, callback)
  • 后台线程自动运行
  • 回调机制通知设备事件

适用场景

  • HDMI 显示器热插拔检测
  • USB 设备监控
  • 设备动态发现
  • 设备状态监控

依赖关系

  • 依赖: Linux libudev 库, epoll
  • 被依赖: DeviceController, CameraController 等模块

类分析

UdevMonitor 类

职责与用途

UdevMonitor 是 udev 设备监控的单例封装类,提供:

  • 单例模式
  • 静态注册方法
  • 自动启动后台线程
  • epoll + udev_monitor 监听事件

设计模式

  • 单例模式: 全局唯一实例
  • 回调机制: 通过回调通知事件
  • 自动管理: 首次注册时自动启动后台线程

类型定义

Callback - 回调类型

using Callback = std::function<void()>;

说明: 设备事件回调函数,无参数,无返回值


公共 API 方法

instance() - 获取单例

static UdevMonitor& instance();

参数说明: 无

返回值: UdevMonitor 单例引用

所有权归属:

  • 只读访问,不转移所有权

注意事项:

  1. 全局唯一实例
  2. 线程安全

registerHandler() - 注册回调处理函数

static void registerHandler(const std::string& subsystem,
                            const std::vector<std::string>& actions,
                            Callback cb);

参数说明:

  • subsystem (输入): 设备子系统(如 "drm", "video4linux")
  • actions (输入): 关心的动作列表(如 {"add", "remove", "change"})
  • cb (输入): 匹配时调用的回调函数

返回值: 无

所有权归属:

  • Callback 由调用者提供

注意事项:

  1. 注册时会自动构造 predicate
  2. 在第一次注册时自动启动后台线程
  3. 回调在后台线程中执行
  4. 避免在回调中执行耗时操作

使用例程:

// 注册 video4linux 设备的 add 和 remove 事件
UdevMonitor::registerHandler("video4linux", 
    {"add", "remove"}, 
    []() {
        printf("Video device event\n");
        // 处理设备事件
    });

// 注册 drm 设备的 change 事件
UdevMonitor::registerHandler("drm", 
    {"change"}, 
    []() {
        printf("DRM device changed\n");
        // 重新扫描显示设备
    });

stop() - 停止监听

static void stop();

参数说明: 无

返回值: 无

所有权归属:

  • 无所有权转移

注意事项:

  1. 主动停止监听(通常不需要手动调用)
  2. 程序退出时单例析构会自动 stop

使用例程:

// 停止监听
UdevMonitor::stop();

内部实现

Handler 结构体

struct Handler {
    std::function<bool(const std::string& subs, const std::string& act)> pred;
    Callback cb;
};

说明: 保存 predicate 和 callback

资源

struct udev* udev_{nullptr};
struct udev_monitor* monitor_{nullptr};
int epollFd_{-1};
int monitorFd_{-1};

后台线程

std::thread worker_;
std::atomic<bool> running_{false};

说明: 后台线程执行事件循环

handlers_

std::mutex handlersMutex_;
std::vector<Handler> handlers_;

说明: 存储所有注册的处理器


线程安全说明

同步机制

  • handlersMutex_: 保护 handlers_ 向量
  • running_: 原子标志,控制后台线程运行状态
  • epoll + udev_monitor: 监听 udev 事件

线程安全建议

  • registerHandler() 是线程安全的
  • stop() 是线程安全的
  • 回调在后台线程中执行,需要线程安全

典型使用场景

场景 1: 监控视频设备

// 注册 video4linux 设备的 add 和 remove 事件
UdevMonitor::registerHandler("video4linux", 
    {"add", "remove"}, 
    []() {
        printf("Video device event\n");
        // 处理设备事件
        refresh_cameras();
    });

场景 2: 监控 DRM 设备

// 注册 drm 设备的 change 事件
UdevMonitor::registerHandler("drm", 
    {"change"}, 
    []() {
        printf("DRM device changed\n");
        // 重新扫描显示设备
        refresh_display();
    });

场景 3: 监控 USB 设备

// 注册 usb 设备的 add 事件
UdevMonitor::registerHandler("usb", 
    {"add"}, 
    []() {
        printf("USB device added\n");
        // 处理 USB 设备
    });

场景 4: 多事件监听

// 注册多个处理器
UdevMonitor::registerHandler("video4linux", 
    {"add"}, 
    []() {
        printf("Camera added\n");
    });

UdevMonitor::registerHandler("video4linux", 
    {"remove"}, 
    []() {
        printf("Camera removed\n");
    });

UdevMonitor::registerHandler("drm", 
    {"change"}, 
    []() {
        printf("Display changed\n");
    });

场景 5: 队列传递事件

// 使用队列传递事件到其他线程
SafeQueue<std::string> event_queue;

UdevMonitor::registerHandler("video4linux", 
    {"add", "remove"}, 
    [&]() {
        event_queue.push("video_event");
    });

// 处理线程
std::thread processor([&]() {
    while (running) {
        std::string event;
        if (event_queue.try_dequeue(event)) {
            handle_event(event);
        }
    }
});

注意事项

  1. 单例模式: 使用静态方法 registerHandler() 和 stop()
  2. 自动启动: 首次注册时自动启动后台线程
  3. 回调线程: 回调在后台线程中执行,不要阻塞
  4. 线程安全: 回调函数应该是线程安全的
  5. 子系统名称: 确保子系统名称正确(如 "drm", "video4linux")
  6. 动作列表: actions 是动作列表(如 {"add", "remove"})
  7. 自动停止: 程序退出时单例析构会自动 stop
  8. libudev: 依赖 Linux libudev 库

常见子系统

子系统 说明 常见动作
video4linux 视频设备 add, remove, change
drm DRM 显示设备 add, remove, change
usb USB 设备 add, remove
input 输入设备 add, remove
sound 音频设备 add, remove, change

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally