Linux使用 Netlink 捕获 USB 热插拔事件
1.前言
在 Qt 中使用 Netlink 来捕获 USB 热插拔事件需要结合 Qt 的事件循环机制和 Netlink 的底层接口。Netlink 是 Linux 内核和用户空间之间的一种通信机制,适用于捕获内核事件(例如 USB 设备的插拔事件)。
以下是一个使用 Qt 和 Netlink 捕获 USB 热插拔事件的示例。
2. 设置 Netlink 套接字
首先,我们需要设置一个 Netlink 套接字来接收内核发送的事件。
3. 将 Netlink 套接字与 Qt 的事件循环集成
使用 Qt 的 QSocketNotifier
类,可以将 Netlink 套接字集成到 Qt 的事件循环中,从而在事件发生时接收通知。
4. 处理 USB 插拔事件
处理 Netlink 消息并解析 USB 插拔事件。
5.代码示例
1.头文件 (usbmonitor.h)
#ifndef USBMONITOR_H
#define USBMONITOR_H
#include <QObject>
#include <QSocketNotifier>
#include <linux/netlink.h>
#include <sys/socket.h>
class USBMonitor : public QObject
{
Q_OBJECT
public:
USBMonitor(QObject *parent = nullptr);
~USBMonitor();
signals:
void usbDeviceAdded();
void usbDeviceRemoved();
private slots:
void handleNetlinkMessage();
private:
int netlinkSocket;
QSocketNotifier *socketNotifier;
void setupNetlinkSocket();
};
2.源文件(usbmonitor.cpp)
#include "usbmonitor.h"
#include <QDebug>
#include <unistd.h>
USBMonitor::USBMonitor(QObject *parent)
: QObject(parent), netlinkSocket(-1), socketNotifier(nullptr)
{
setupNetlinkSocket();
}
USBMonitor::~USBMonitor()
{
if (socketNotifier) {
delete socketNotifier;
}
if (netlinkSocket != -1) {
close(netlinkSocket);
}
}
void USBMonitor::setupNetlinkSocket()
{
netlinkSocket = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (netlinkSocket == -1) {
qFatal("Failed to create Netlink socket");
}
sockaddr_nl sa;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_pid = getpid();
sa.nl_groups = -1;
if (bind(netlinkSocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
qFatal("Failed to bind Netlink socket");
}
socketNotifier = new QSocketNotifier(netlinkSocket, QSocketNotifier::Read, this);
connect(socketNotifier, &QSocketNotifier::activated, this, &USBMonitor::handleNetlinkMessage);
}
void USBMonitor::handleNetlinkMessage()
{
char buffer[4096];
int len = recv(netlinkSocket, buffer, sizeof(buffer), 0);
if (len == -1) {
qWarning("Failed to receive Netlink message");
return;
}
buffer[len] = '\0';
QString msg(buffer);
if (msg.contains("add@")) {
emit usbDeviceAdded();
} else if (msg.contains("remove@")) {
emit usbDeviceRemoved();
}
}
3.使用示例 (main.cpp)
#include <QCoreApplication>
#include "usbmonitor.h"
void handleDeviceAdded() {
qDebug() << "USB device added!";
}
void handleDeviceRemoved() {
qDebug() << "USB device removed!";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
USBMonitor monitor;
QObject::connect(&monitor, &USBMonitor::usbDeviceAdded, &handleDeviceAdded);
QObject::connect(&monitor, &USBMonitor::usbDeviceRemoved, &handleDeviceRemoved);
return a.exec();
}
6.解释
1.USBMonitor 类:
- 设置 Netlink 套接字并绑定到
NETLINK_KOBJECT_UEVENT
组。 - 使用
QSocketNotifier
来监视 Netlink 套接字的可读事件。
2.handleNetlinkMessage 方法:
- 从 Netlink 套接字接收消息并解析它们。
- 根据消息内容,发射
usbDeviceAdded
或usbDeviceRemoved
信号。
3.main 函数:
- 创建
USBMonitor
实例并连接信号到槽函数以处理 USB 插拔事件。
7.运行
编译并运行程序后,当插入或拔出 USB 设备时,你将在控制台上看到相应的消息。
这种方法结合了 Qt 的事件处理机制和 Linux