Linux下自动检测USB热插拔
做嵌入式开发,尤其在网关、路由器或者其他支持USB设备的终端上,为了提高用户体验,我们常常需要支持自动识别并挂载USB设备功能。某些应用程序,在使用USB设备的过程中,也希望能够侦测到USB断开事件,不至于某些工作因为USB已经不存在而白做。在Linux下,我们主要有两种办法检测USB热插拔。
第一种便是定时检查/proc/scsi/scsi文件,该文件内会按照标准格式保存着当前设备内挂载的存储介质基本信息,如果在PC端,除了硬盘(ATA)、光驱(CD-ROM)外,就是USB设备(Direct-Access)了,轮询该scsi文件,检查文件内是否新增或减少数据便可实现自动侦测USB热插拔的效果。但是这种方法对于热插拔(hotplug)设备,如U盘,效果就没那么理想了,因为我们不知道设备什么时候插上,又是什么时候被拔掉了,只能验证当前是否已经插上或者已经拔除的事实。于是便有了另一种办法,我们采用一种特殊类的的文件描述符(套结字)专门用于Linux内核跟用户空间之间的异步通信,这种技术通常被成为NETLINK。
由于NETLINK是Linux内置功能,所以使用起来很简单:创建一个AF_NETLINK协议族下NETLINK_KOBJECT_UEVENT类型的特殊文件描述符(套结字)CppLive,然后利用setsocketopt允许该文件描述符(套结字)复用其他端口,再利用band函数将自身进程绑定到特殊文件描述符(套结字)CppLive,最后利用select在while循环内监听CppLive是否可读,如果可读则调用recv接收Linux系统内核传递过来的数据并打印出来,这些输出便是USB热插拔信息。当然你也可以个性化地处理来自内核的热插拔信息,让程序变得更加智能以及人性化。
利用NETLINK检测USB热插拔的C语言实现代码如下:
- #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 CppLive, rcvlen, ret;
- fd_set fds;
- int buffersize = 1024;
- CppLive = 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(CppLive, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
- bind(CppLive, (struct sockaddr*)&client, sizeof(client));
- while (1) {
- char buf[UEVENT_BUFFER_SIZE] = { 0 };
- FD_ZERO(&fds);
- FD_SET(CppLive, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = 100 * 1000;
- ret = select(CppLive + 1, &fds, NULL, NULL, &tv);
- if(ret < 0)
- continue;
- if(!(ret > 0 && FD_ISSET(CppLive, &fds)))
- continue;
- /* receive data */
- rcvlen = recv(CppLive, &buf, sizeof(buf), 0);
- if (rcvlen > 0) {
- printf("%s\n", buf);
- /*You can do something here to make the program more perfect!!!*/
- }
- }
- close(CppLive);
- return 0;
- }
运行程序,测试U盘插入/拔除,输出如下:
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0
- add@/module/usb_storage
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6
- add@/bus/usb/drivers/usb-storage
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
- change@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb
- add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4
- add@/devices/virtual/bdi/8:16
- add@/module/fat
- add@/kernel/slab/fat_cache
- add@/kernel/slab/fat_inode_cache
- add@/module/vfat
- add@/module/nls_cp437
- add@/module/nls_iso8859_1
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4
- remove@/devices/virtual/bdi/8:16
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0
- remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1
- remove@/host6/target6:0:0
转自http://www.cpplive.com/html/1355.html
Linux下自动检测USB热插拔相关推荐
- qt linux下自动检测U盘热插拔
如果用U盘来更新软件,需要先删除当前的可执行文件,但是如果删除之后,复制失败的话会导致后续没有文件可以运行了.一个方法是将新的可执行文件放到另一个目录中,当copy成功后修改linux的启动文件,然后 ...
- Linux系统下自动搜索USB摄像头地址及设备信息
Linux系统下自动搜索USB摄像头地址及设备信息 在进行到多个USB摄像头开发时,会涉及到获取摄像头地址及设备信息问题. 一般USB摄像头的设备信息是固定的,我们基于设备信息,就可以在软件开发时进行 ...
- linux 杂项设备,Linux下自动创建节点的字符杂项设备 misc_register
Linux下自动创建节点的字符杂项设备 misc_register admin • 2020 年 01 月 07 日 杂项设备 Linux里面的misc杂项设备是主设备号为10的驱动设备 定义头文件: ...
- Linux下,查看USB设备信息
Linux下,查看USB设备信息 首先需要将usbfs挂载一下,然后才能查看. $ mount -t usbfs none /proc/bus/usb $ cat /proc/bus/usb/dev ...
- linux备份mysql怎样操作,Linux下自动备份MySQL数据库详细操作步骤(转载)
环境说明 操作系统:CentOS IP:192.168.150.214 Oracle数据库版本:Oracle11gR2 用户:root 密码:123456 端口:3306 数据库:ts_0.ts_1. ...
- Linux下自动备份Oracle数据库并删除指定天数前的备份
说明: Oracle数据库服务器 操作系统:CentOS IP:192.168.0.198 端口:1521 SID:orcl Oracle数据库版本:Oracle11gR2 具体操作: 1.root用 ...
- Linux下自动重启系统
Linux下自动重启系统 1. 在/root下新建一个计数文件count.txt ,编辑内容为 初始值1 2. 在/root下写一个reboot.sh的脚本文件(注意空格!!!) #/bi ...
- Linux下内存检测工具:asan
Linux下内存检测工具:asan ASAN(Address-Sanitizier)早先是LLVM中的特性,后被加入GCC 4.8,在GCC 4.9后加入对ARM平台的支持.因此GCC 4.8以上版本 ...
- aix oracle备份命令,Aix/Linux下自动备份oracle数据库
曾经有个同事,来回操作开发和生产的数据库,结果误删了生产的数据库,那种心情我想不是一般人能理解的,虽然说oracle可以有方法还原,但并不是彻底的. 所以,在工作中,不管是开发还是维护,备份数据库是非 ...
最新文章
- 股市币市:数据分析与交易所公告(20190227)
- linux没有交换分区会怎样,linux – 服务器拒绝使用交换分区
- Python 面试题:输入一个数组,输出该数组的第二大的数字
- Servlet_生命周期方法
- centons7网卡配置文件使用openvswitch bridge
- Scala连接mongodb数据库
- 装载服务器安装和配置_一站式解决方案
- 第65课 采访报道 《小学生C++趣味编程》
- C++/C--STL API查询及免费教程网站
- ps 如何增加 填充图案
- 打印流-PrintStream和PrintWriter
- 网络安全实战之靶场渗透技术
- 004-中国五个城市PM 2.5数据分析
- Godaddy域名被盗诉讼全过程 法院起诉成功拿回域名
- ROS创建Publisher理解
- Grow up way
- java mongodb gridfs_MongoDB-4 GridFS 文件存储
- spss基础-5.10
- Linux雷鸟邮件,thunderbird雷鸟mail
- AS打开照相机拍照保存本地、显示页面