如何在Linux系统中有效检测USB设备的插拔事件?

在Linux系统中检测USB设备的插拔事件,可以通过多种方法实现,以下将详细介绍几种常见的方法:

如何在Linux系统中有效检测USB设备的插拔事件?插图1

使用 `lsusb` 命令

原理

lsusb 是一个用于列出当前连接的USB设备的命令,通过定期运行该命令并比较输出结果,可以检测USB设备的插入和拔出。

示例代码(Python

import subprocess
def list_usb_devices():
    result = subprocess.run(['lsusb'], capture_output=True, text=True)
    return result.stdout
def detect_usb_change(previous_output):
    current_output = list_usb_devices()
    if current_output != previous_output:
        print("USB device changed!")
    return current_output
if __name__ == "__main__":
    previous_output = ""
    while True:
        current_output = detect_usb_change(previous_output)
        previous_output = current_output

使用 `udev` 库

原理

udev 是Linux系统中用于动态管理设备节点的守护进程,通过监听udev 事件,可以实时检测USB设备的插拔。

示例代码(C)

如何在Linux系统中有效检测USB设备的插拔事件?插图3

#include <libudev.h>
#include <stdio.h>
int main() {
    struct udev *udev = udev_new();
    if (!udev) {
        fprintf(stderr, "Cannot create udev context
");
        return 1;
    }
    struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
    udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL);
    udev_monitor_enable_receiving(mon);
    while (1) {
        struct udev_device *dev = udev_monitor_receive_device(mon);
        if (dev) {
            const char *action = udev_device_get_action(dev);
            if (strcmp(action, "add") == 0 || strcmp(action, "remove") == 0) {
                printf("USB device %s
", action);
            }
            udev_device_unref(dev);
        }
    }
    udev_unref(udev);
    return 0;
}

使用 `Netlink` 机制

原理

Netlink 是一种内核与用户空间的通信机制,适用于捕获内核事件(例如USB设备的插拔)。

示例代码(C)

#include <linux/netlink.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define UEVENT_BUFFER_SIZE 2048
int main() {
    int CppLive = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    if (CppLive < 0) {
        perror("socket");
        return -1;
    }
    struct sockaddr_nl client;
    memset(&client, 0, sizeof(client));
    client.nl_family = AF_NETLINK;
    client.nl_pid = getpid();
    client.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
    bind(CppLive, (struct sockaddr *)&client, sizeof(client));
    while (1) {
        char buf[UEVENT_BUFFER_SIZE] = { 0 };
        int rcvlen = recv(CppLive, &buf, sizeof(buf), 0);
        if (rcvlen > 0) {
            printf("%s
", buf);
        }
    }
    close(CppLive);
    return 0;
}

4. 使用Qt 框架中的QProcess

原理

利用Qt 提供的QProcess 类来启动外部进程,并通过解析其输出来检测USB设备的插拔,这种方法不需要了解USB接口的底层细节。

如何在Linux系统中有效检测USB设备的插拔事件?插图5

示例代码(C++)

#include <QCoreApplication>
#include <QProcess>
#include <QStringList>
#include <QByteArray>
#include <QDebug>
int usbCount(const QString &vendor) {
    QProcess process;
    QStringList args;
    if (!vendor.isEmpty()) {
        args << "-d" << vendor;
    }
    process.start("lsusb", args);
    process.waitForFinished();
    QString result = QString(process.readAllStandardOutput());
    QStringList outputList = result.split("
");
    return outputList.count(); //返回可能包含一行空字符行,但是不影响检测结果
}
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    int usbCnt = -1;
    bool usbChanged = true;
    QString argd = "096e:0303"; // USB设备的venderID和productID,这个是可以预知的,当然不输入也可以
    do {
        int usbCnt_new = usbCount(argd);
        if (usbCnt == usbCnt_new) {
            usbChanged = false;
        } else {
            usbChanged = true;
        }
        usbCnt = usbCnt_new;
        if (usbChanged) {
            // yes!
            QThread::sleep(2000); // 休眠2秒以避免频繁检测
        }
    } while (true);
    return a.exec();
}

以下是对这几种方法的详细对比:

方法 优点 缺点 适用场景
lsusb 简单易用,无需额外依赖 需要定期轮询,资源消耗较大 简单的USB设备监控
udev 实时性强,适合系统级应用 需要了解udev库的使用 嵌入式系统、复杂应用
Netlink 高效,适合高性能需求 实现复杂,需要处理内核消息 高性能需求的应用
Qt + QProcess 跨平台,集成方便 依赖于Qt框架 Qt应用程序中集成USB监控

Linux下检测USB设备的插拔有多种方法,可以根据具体需求选择合适的方案,无论是简单的脚本还是复杂的系统级应用,都有相应的解决方案。

以上就是关于“linux 检测usb插拔”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!

本文来源于互联网,如若侵权,请联系管理员删除,本文链接:https://www.9969.net/85857.html

小末小末
上一篇 2024年10月27日 17:34
下一篇 2024年10月27日 17:50

相关推荐