【发布时间】:2020-06-15 13:17:41
【问题描述】:
我正在开发一个用于嵌入式设备的 C++ 应用程序,该应用程序通过 netlink 套接字侦听 USB 热插拔事件。检测事件完美无缺,但另外我想在程序开始时查询已经连接的设备。我能够为网络接口存档相同的功能,但似乎 USB 是一个完全不同的故事。所以我的问题是:
- 是否甚至可以使用 netlink 套接字列出已连接的 USB 设备?
- 如果可能,请求消息会是什么样子?
- 如果不可能,那么什么是依赖很少的好选择?
用于接收热插拔事件的 MWE:
#include <sys/signalfd.h>
#include <csignal>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <cstdio>
#include <poll.h>
int main() {
struct sockaddr_nl addr = {0};
char buffer[4096];
sigset_t signal_set;
struct signalfd_siginfo signal_info;
struct pollfd pfd[2];
int ret_poll;
ssize_t n;
// Set signals we want to catch
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGTERM);
sigaddset(&signal_set, SIGINT);
// Change the signal mask and check
if (sigprocmask(SIG_BLOCK, &signal_set, nullptr) < 0) {
fprintf(stderr, "Error while sigprocmask(): %s\n", strerror(errno));
return EXIT_FAILURE;
}
// Get a signal file descriptor
pfd[0].fd = signalfd(-1, &signal_set, 0);
// Check the signal file descriptor
if (pfd[0].fd < 0) {
fprintf(stderr, "Error while signalfd(): %s\n", strerror(errno));
return EXIT_FAILURE;
}
// Create a netlink socket
pfd[1].fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (pfd[1].fd < 0) {
fprintf(stderr, "Netlink socket create failed: %s\n", strerror(errno));
return EXIT_FAILURE;
}
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 2;
if (bind(pfd[1].fd, (struct sockaddr *) &addr, sizeof(addr))) {
fprintf(stderr, "Netlink socket bind() failed: %s\n", strerror(errno));
return EXIT_FAILURE;
}
pfd[0].events = POLLIN;
pfd[1].events = POLLIN;
while (true) {
// Wait for events without time limit
ret_poll = poll(pfd, 2, -1);
if (ret_poll < 0) {
fprintf(stderr, "SystemMaster::execute() -> "
"Error while poll(): %s\n", strerror(errno));
return EXIT_FAILURE;
}
// True, if a signal from the operating system was sent to this process
if (pfd[0].revents & POLLIN) {
// Get the signal
n = read(pfd[0].fd, &signal_info, sizeof(signal_info));
// True, if an error occurred while getting the signal
if (n == -1) {
fprintf(stderr, "Error while read() on signal pipe: %s\n", strerror(errno));
}
// Check, if we are really interested in the caught signal
if ((signal_info.ssi_signo == SIGTERM) || (signal_info.ssi_signo == SIGINT)) {
printf("Signal received\n");
}
break;
}
// True, if a netlink message is available
if (pfd[1].revents & POLLIN) {
n = recv(pfd[1].fd, &buffer, sizeof(buffer), 0);
for (int i = 0; i < n; ++i) {
if (buffer[i] == 0) printf("\n");
else if (buffer[i] > 33 && buffer[i] < 126) printf("%c", buffer[i]);
}
}
}
// Close both file descriptors
close(pfd[0].fd);
close(pfd[1].fd);
return 0;
}
提前感谢您的任何回复!
【问题讨论】:
-
查看
lsusb及其来源。 -
@UlrichEckhardt,我什至建议使用它。
标签: c++ linux linux-kernel embedded-linux netlink