通过Netlink检测USB设备的插拔

    在Android的Vold里面可以了解到,其检测USB的插拔是通过Netlink机制来实现的,那我们也来尝试下如何在Linux下写个程序检测USB设备的插拔,下面我们将使用Netlink的NETLINK_KOBJECT_UEVENT类型套接字与Kernel进行通信,然后使用setsocketopt()来利用该套接字,再使用select()并发检测相应的套接写是否可操作,具体的代码实现 如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#define UEVENT_BUFFER_SIZE 2048

int main(void)
{
    struct sockaddr_nl client;
    struct timeval tv;
    int fd, rcvlen, ret;
    fd_set fds;
    int buffersize = 1024;

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    memset(&client, 0, sizeof(client));

    client.nl_family = AF_NETLINK;
    client.nl_pid = getpid();
    client.nl_groups = 1; /* receive broadcast message*/

    setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
    bind(fd, (struct sockaddr*)&client, sizeof(client));

    while (1) {
        char buf[UEVENT_BUFFER_SIZE] = { 0 };
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        tv.tv_sec = 0;
        tv.tv_usec = 100 * 1000;

        ret = select(fd + 1, &fds, NULL, NULL, &tv);
        if(ret < 0)
            continue;

        if(!(ret > 0 && FD_ISSET(fd, &fds)))
            continue;

        /* receive data */
        rcvlen = recv(fd, &buf, sizeof(buf), 0);
        if (rcvlen > 0) {
            printf("%s\n", buf);
            /*You can do something here to make the program more perfect!!!*/
        }
    }
    close(fd);
    return 0;
}

    然后将其交叉编译下并放到我们的Mstar板卡上,插拔U盘和USB鼠标时有如下提示:

add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2
add@/devices/platform/Mstar[  120.529879] scsi0 : usb-storage 4-1.2:1.0-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0
add@/devices[  120.537275] isa bounce pool size: 16 pages/platform/Mstar-[  120.543612] scsi 0:0:0:0: Direct-Access     SanDisk  Cruzer Blade     2.01 PQ: 0 ANSI: 5
ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0
add@/de[  120.556037] sd 0:0:0:0: [sda] 7821312 512-byte logical blocks: (4.00 GB/3.72 GiB)
vices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1[  120.567115] sd 0:0:0:0: [sda] Write Protect is off
.2:1.0/host0/scs[  120.573404] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
i_host/host0
add@/devices/platform/Mstar-ehci-2[  120.587278] emmc_partition()
.1/usb4/4-1/4-1.2/usb_device/usbdev4.4
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.[  120.598422] 0x0
2:1.0/host0/targ[  120.600753]  sda: sda1
et0:0:0
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/scsi_device[  120.629463] sd 0:0:0:0: [sda]
Attached SCSI removable disk
/0:0:0:0
add@/devices/virtual/bdi/8:0
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/block/sda
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-[  163.282004] input: PIXART USB OPTICAL MOUSE as /devices/platform/Mstar-ehci
2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input10
1.4/4-1.4:1.0
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1[  163.297335] generic-usb 0003:093A:2510.0003: input,hidraw1: USB HID v1.11 Mouse
[PIXART USB OPTICAL MOUSE] on usb-mstar-1.4/input0
.4/4-1.4:1.0/0003:093A:2510.0003
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input10
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input10/mouse2
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input10/event4
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/0003:093A:2510.0003/hidraw/hidraw1
add@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/usb_device/usbdev4.5
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0
remove@/devices/virtual/bdi/8:0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0/block/sda
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0/0:0:0:0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/target0:0:0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0/scsi_host/host0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0/host0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/4-1.2:1.0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2/usb_device/usbdev4.4
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.2
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input4/mouse2
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input4/event4
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/input/input4
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/0003:093A:2510.0002/hidraw/hidraw1
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0/0003:093A:2510.0002
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/4-1.4:1.0
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4/usb_device/usbdev4.3
remove@/devices/platform/Mstar-ehci-2.1/usb4/4-1/4-1.4

    从上面的打印信息,我们看到插入时会以add@开头,而拔掉时会以remove@开头,通过判断这样的头部信息可以判断是不是有设备进行插拔,进而再处理后面的内容来判断具体是哪个设备。

参考网址:

http://www.cpplive.com/html/1355.html
http://www.linuxidc.com/Linux/2012-02/53354.htm
http://www.linuxidc.com/Linux/2011-12/49112.htm



作者:网路元素
链接:https://www.jianshu.com/p/c772eeea3217
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的C程序,使用netlink获取usb设备插拔事件,并提取设备类型,名字,pid vid 文件路径等信息: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <linux/usb/ch9.h> #define UEVENT_BUFFER_SIZE 2048 int main() { struct sockaddr_nl nls; struct msghdr msg; struct iovec iov; char buffer[UEVENT_BUFFER_SIZE]; int ret, fd, len; struct nlmsghdr *nh; struct udev_device *dev; char *action, *subsystem, *devtype, *devname, *pid, *vid, *path; memset(&nls, 0, sizeof(nls)); nls.nl_family = AF_NETLINK; nls.nl_pid = getpid(); nls.nl_groups = -1; if ((fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT)) == -1) { perror("socket"); exit(EXIT_FAILURE); } if (bind(fd, (struct sockaddr *)&nls, sizeof(nls)) == -1) { perror("bind"); exit(EXIT_FAILURE); } memset(&msg, 0, sizeof(struct msghdr)); iov.iov_base = buffer; iov.iov_len = sizeof(buffer); msg.msg_name = (void *)&nls; msg.msg_namelen = sizeof(nls); msg.msg_iov = &iov; msg.msg_iovlen = 1; while (1) { len = recvmsg(fd, &msg, 0); if (len == -1) { perror("recvmsg"); exit(EXIT_FAILURE); } nh = (struct nlmsghdr *)buffer; while (NLMSG_OK(nh, len)) { if (nh->nlmsg_type == NLMSG_DONE) break; else if (nh->nlmsg_type == NLMSG_ERROR) { perror("NLMSG_ERROR"); exit(EXIT_FAILURE); } else if (nh->nlmsg_type == UDEV_MONITOR) { action = strstr(NLMSG_DATA(nh), "ACTION="); if (action != NULL) { subsystem = strstr(NLMSG_DATA(nh), "SUBSYSTEM="); devtype = strstr(NLMSG_DATA(nh), "DEVTYPE="); devname = strstr(NLMSG_DATA(nh), "DEVNAME="); pid = strstr(NLMSG_DATA(nh), "ID_VENDOR_ID="); vid = strstr(NLMSG_DATA(nh), "ID_PRODUCT_ID="); path = strstr(NLMSG_DATA(nh), "DEVPATH="); if (action != NULL && subsystem != NULL && devtype != NULL && devname != NULL && pid != NULL && vid != NULL && path != NULL) { printf("Action: %s\n", action + strlen("ACTION=")); printf("Subsystem: %s\n", subsystem + strlen("SUBSYSTEM=")); printf("Devtype: %s\n", devtype + strlen("DEVTYPE=")); printf("Devname: %s\n", devname + strlen("DEVNAME=")); printf("Pid: %s\n", pid + strlen("ID_VENDOR_ID=")); printf("Vid: %s\n", vid + strlen("ID_PRODUCT_ID=")); printf("Path: %s\n", path + strlen("DEVPATH=")); printf("\n"); } } } nh = NLMSG_NEXT(nh, len); } } close(fd); return 0; } ``` 这个程序使用了netlink套接字来接收内核发送的消息,然后解析消息中的信息,提取出usb设备的相关信息,包括设备类型,名字,pid vid 文件路径等信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值