netlink 实现usb插拔监测,并且要求recv不能阻塞通过轮询获取,并且不能用epoll,请用C语言写出程序
时间: 2024-03-02 18:54:10 浏览: 108
好的,下面是一个简单的示例程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024
int main() {
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct msghdr msg;
struct iovec iov;
int sock_fd;
char buffer[MAX_PAYLOAD];
// 创建socket
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
printf("Error creating socket\n");
return -1;
}
// 初始化源地址
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
// 绑定socket到源地址
if (bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0) {
printf("Error binding socket\n");
close(sock_fd);
return -1;
}
// 初始化目标地址
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; // 内核接收所有的消息
dest_addr.nl_groups = 1; // 接收所有的组播消息
// 准备发送消息
nlh = (struct nlmsghdr*)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, sizeof(struct nlmsghdr));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
// 发送消息到内核
iov.iov_base = (void*)nlh;
iov.iov_len = nlh->nlmsg_len;
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void*)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd, &msg, 0);
// 接收内核发送的消息
while (1) {
memset(buffer, 0, MAX_PAYLOAD);
iov.iov_base = (void*)buffer;
iov.iov_len = MAX_PAYLOAD;
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void*)&src_addr;
msg.msg_namelen = sizeof(src_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// 调用recv函数时设置MSG_DONTWAIT标志,避免阻塞
recv(sock_fd, &msg, MSG_DONTWAIT);
printf("%s\n", buffer);
}
// 关闭socket
close(sock_fd);
return 0;
}
```
这个程序首先创建一个NETLINK_USER类型的socket,并将其绑定到当前进程的PID上。然后它准备了一个NLMSG_SPACE(MAX_PAYLOAD)大小的消息结构体,并将其发送给内核。最后,程序进入一个无限循环,轮询接收内核发送的消息,每次接收到消息后都将其打印出来。
注意,这个程序并没有实现usb插拔监测的具体功能,只是接收内核发送的消息并打印出来。如果要实现usb插拔监测功能,需要根据实际需求编写相应的内核模块,并在模块中使用netlink协议与用户空间通信。
阅读全文