方式一
通过udev规则监听设备事件,编写/etc/udev/rules.d/99-udev-mount.rules规则实现U盘插入捕获U盘插入事件
1 2 3 4 5
| ACTION=="add", KERNEL=="sd[a-z]*", RUN+="/bin/mkdir -p /media/udev-%k", RUN+="/bin/mount /dev/%k /media/udev-%k"
ACTION=="remove", KERNEL=="sd[a-z]*", RUN+="/bin/umount /media/udev-%k"
|
规则编辑完成后执行以下命令使规则生效
1
| sudo udevadm control --reload
|
我们在开发嵌入式产品时,会需要U盘读写功能,但是Linux系统不像Windows系统那样能默认配置U盘自动挂载,所以我们需要在Linux系统中手动添加rule规则,实现U盘自动挂载功能。
Udev规则
是什么?
udev 是Linux 系统的一个设备管理器,它主要的功能是管理/dev目录底下的设备节点。
特色功能是对设备有极端需求的站点(比如需要控制上千个硬盘)和热插拔设备(比如USB摄像头和MP3播放器)有着较完善的处理能力。
比如在处理热插拔设备时,udev在用户空间,根据用户设置的规则,在监测到设备被插入后,在/dev/下自动创建并命名设备文件节点 或者 自动设置设备属性。
溯源历史
早期:通过mknod静态添加
中期:devfs基于内核的动态设备文件系统
现在:udev 一个用户空间程序
Udev和Devfs的区别
1.devfs运行在内核空间(使用devfs_register等API在内核空间注册设备节点),而udev运行在用户空间。
2.当用户访问/dev下的某个节点时,devfs会自动加载对应的驱动;而udev则并不负责自动加载驱动的工作。
Udev的热插拔工作机制
Udev工作在用户空间,当一个设备被插入或者移除时,内核会通过netlink套接字发送设备详细信息到用户空间,udev获取到设备信息,根据信息内容在/dev下创建并命名设备节点 或者 配置属性。
Udev的配置规则
1.配置文件
主配置文件: /etc/udev/udev.conf
udev_root=”/dev/“ 设备目录,默认是/dev
udev_rules=”/etc/udev/rules.d/“ udev规则存储的目录
udev_log=”err” 日志等级(表示严重程度),跟 syslog 一致,例如: err, info, debug
2.规则文件
udev的规则文件一般位于 /lib/udev/rules.d/,有的位于 /etc/udev/rules.d/下。
规则文件是按照字母顺序处理的,不管放在哪个目录。对于相同名字的规则文件, /etc/udev/rules.d 比 /lib/udev/rules.d 优先。
规则文件必须以.rules 作为扩展名,否则不被当作规则文件。
规则文件的每一行都是 key=value 格式。 key 有两个类型:1)匹配型 key 2)赋值型 key
当所有匹配型 key 都匹配时,该规则即被采用,赋值型 key就会获得相应的值。
一条规则由多个key=value 组成,以英文逗号隔开。 每个key 有一个操作,取决于操作符,有效的操作符如下:
== 比较是否相等
!= 比较是否不相等
= 给一个key 赋值。表示一个列表的key会被重置,并且把这个唯一的值传给它
+= 将一个值增加到key中
:= 将一个值传给一个key,并且不允许再修改这个key。
3.匹配型Key
ACTION: 事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 )。
KERNEL: 内核设备名称,例如:sda, cdrom。
DEVPATH: 设备的 devpath 路径。
SUBSYSTEM: 设备的子系统名称,例如:sda 的子系统为 block。
BUS: 设备在 devpath 里的总线名称,例如:usb。
DRIVER: 设备在 devpath 里的设备驱动名称,例如:ide-cdrom。
ID: 设备在 devpath 里的识别号。
SYSFS{filename}: 设备的 devpath 路径下,设备的属性文件“filename”里的内容。例如:SYSFS{model}==“ST936701SS”表示:如果设备的型号为 ST936701SS,则该设备匹配该 匹配键。在一条规则中,可以设定最多五条 SYSFS 的 匹配键。
ENV{key}: 环境变量。在一条规则中,可以设定最多五条环境变量的 匹配键。
PROGRAM: 调用外部命令。
RESULT: 外部命令 PROGRAM 的返回结果。
通配符 * 代表 [ 0 个到无穷多个 ] 任意字符
通配符 ? 代表 [一定有一个] 任意字符
通配符 [ ] 代表 [一定有一个在括号内] 的字符(非任意字符)
4.赋值型 Key
NAME: 在 /dev下产生的设备文件名。只有第一次对某个设备的 NAME 的赋值行为生效,之后匹配的规则再对该设备的 NAME 赋值行为将被忽略。如果没有任何规则对设备的 NAME 赋值,udev 将使用内核设备名称来产生设备文件。
SYMLINK: 为 /dev/下的设备文件产生符号链接。由于 udev 只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的 udev 规则所产生的文件,推荐使用符号链接。
LABEL GOTO 可以跳到的地方
GOTO 跳到下一个带有匹配名字的 LABEL 处。
ENV{key}: 导入一个环境变量。
OWNER, GROUP, MODE: 为设备设定权限。
$kernel, %k: 该设备的内核名字(%k 替换$kernel)
$number, %n:该设备的内核号码。例如 sda3 的内核号码是 3。
$devpath, %p: 该设备的 devpath
$id, %b:当向上搜索devpath,寻找 SUBSYSTEMS, KERNELS, DRIVERS 和 ATTRS 时,被匹配的设备名字
$driver: 当向上搜索devpath,寻找 SUBSYSTEMS, KERNELS, DRIVERS 和 ATTRS 时,被匹配的驱动名字
$attr { file }, %s { file }: 一个被发现的设备的sysfs 属性的值。如果该设备没有该属性,且前面的 KERNELS, SUBSYSTEMS, DRIVERS或 ATTRS 测试选择的是一个父设备,那么就用父设备的属性。如果属性是一个符号链,符号链的最后一个元素作为返回值。
$env { key }, %E { key }: 一个设备属性值
$major, %M: 该设备的内核主号码
$minor, %m: 该设备的内核次号码
$result, %c: 由 PROGRAM 调用的外部程序返回的字符串。如果这个字符串包含空格,可以用 %c{N} 选中第N个字段。如果这个数字N,后面有一个 + 字符, 则表示选中从这个字段开始的所有后面的字符串 %c { N + }
$parent, %p:父设备的节点名字
$name:设备节点的名字,用一个空格作为分隔符。该值只有在前面的规则赋值之后才存在,或者是remove事件。
$links:当前符号链的列表,用空格隔开。该值只有在前面的规则赋值之后才存在,或者是remove事件。
$root, %r:udev_root 的值
$sys, %S:sysfs 挂载点
$tempnode, %N:在真正的设备节点创建之前,创建的一个临时的设备节点的名字,这个临时设备节点供外部程序使用。
$$: ‘$’字符自己
%%: ‘%’ 字符自己
Udev的应用举例
前提是系统里存在udev工具
在/etc/udev/rules.d/下添加usb-mount.rules规则,参考如下:
KERNEL!= "sd[a-z][0-9]"``,GOTO= "automount_exit"
ACTION== "add"``, SUBSYSTEMS== "usb"``, SUBSYSTEM== "block"``,RUN+= "/bin/mkdir /mnt/usb"``,RUN+= "/bin/mount --no-block --automount=yes $devnode /mnt/usb"
ACTION== "remove"``, RUN+= "/bin/umount /mnt/usb"``,RUN+= "/bin/rmdir /mnt/usb"
LABEL= "automount_exit"
以上例子中的udev规则中匹配sd[a-z][0-9]的设备, 当系统中检查usb设备插入时, 就会执行add中的操作, 当检查到usb设备拔出后, 就会执行remove中的操作。
规则中的remove操作是在拔出U盘后执行的, 为了保证写入U盘的数据不丢失, 在拔出U盘之前需要执行sync命令把数据写入U盘中。
在有的Linux里,存在systemd服务的话,尽量还是用systemd的mount和umount为好。
欢迎转载,欢迎指正,更欢迎点赞。转载请附原文链接。
posted @ Aaron看世界 阅读(3264) 评论(0) 收藏 举报
公告

|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
|---|
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 | 1 | 2 | 3 | 4 | 5 | 6 |
字节旗下的 AI IDE
AI 搜索
使用netlink捕获USB插拔事件
最新推荐文章于 2024-06-14 14:01:01 发布
SlamDunk31598 于 2019-02-20 20:26:28 发布
CC 4.0 BY-SA版权
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/yangchao315/article/details/87820406
使用netlink捕获USB插拔事件
Linux 中使用udev来管理热插拔,使用netlink监听udev的消息可以为用户空间提供管理策略,通过解析消息中的字符串来完成控制逻辑。
USB的热插拔应用广泛,比如U盘、手机、USB网卡等等,netlink捕获消息后,解析消息中的字符串可以进一步识别是哪种设备,从而在用户空间完成逻辑控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
| #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <fcntl.h> #include <sys/socket.h> #include <linux/netlink.h>
#define UEVENT_BUFFER_SIZE 2048
int main(void) { char buf[UEVENT_BUFFER_SIZE] = { 0 }; struct sockaddr_nl netlink;
int hotplug_sock, rcvlen, ret; int buffersize = 2048;
hotplug_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); memset(&netlink, 0, sizeof(netlink)); netlink.nl_family = AF_NETLINK; netlink.nl_pid = getpid(); netlink.nl_groups = 1; /* receive broadcast message*/
setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); bind(hotplug_sock, (struct sockaddr*)&netlink, sizeof(netlink));
while (1) { memset(buf, 0, sizeof(buf)); /* receive data */ rcvlen = recv(hotplug_sock, &buf, sizeof(buf), 0); if (rcvlen > 0) { /*You can do something here to make the program more perfect!!!*/ printf("%s\n", buf); #if 0 if(strstr(buf, "add@")){ //printf("%s\n", buf); }else if(strstr(buf, "remove@")){ printf("%s\n", buf); system("echo 0 > /sys/bus/i2c/drivers/e52241/0-0011/set_en"); sleep(1); system("echo 1 > /sys/bus/i2c/drivers/e52241/0-0011/set_en"); } #endif } }
close(hotplug_sock); return 0; }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 ```[Linux C高级技巧:利用 *Netlink* 机制检测嵌入式设备的 *USB* 热 *插拔*](https://blog.csdn.net/CodeSageX/article/details/133131520)
[CodeSageX的博客](https://blog.csdn.net/CodeSageX)
09-21 796[*USB* 热 *插拔* 是在运行中插入或拔出 *USB* 设备的过程。在嵌入式系统中,通过 *使用* Linux的 *Netlink* 机制,我们可以实现对 *USB* 设备的热 *插拔* *事件* 进行检测和处理。我们将 *使用* *Netlink* Socket来监听内核 *事件* ,并接收有关 *USB* 设备热 *插拔* 的通知消息。接下来,我们需要解析接收到的 *Netlink* 消息,以 *获取* 有关 *USB* 热 *插拔* *事件* 的信息。在上述代码中的循环中,我们 *使用* recvmsg()函数接收消息,并 *使用* NLMSG\_DATA宏来 *获取* 消息数据。根据接收到的消息,我们可以判断是 *USB* 设备的插入还是拔出 *事件* 。](https://blog.csdn.net/CodeSageX/article/details/133131520)[通过 *Netlink* 检测 *USB* 设备的 *插拔*](https://blog.csdn.net/guochongxin/article/details/140906880)
[
最新发布
](https://blog.csdn.net/guochongxin/article/details/140906880)
[阿xin\*的嵌入式AI](https://blog.csdn.net/guochongxin)
08-06 869[Android/Linux通过 *netlink* 检测 *USB* *插拔* 。](https://blog.csdn.net/guochongxin/article/details/140906880)[*netlink* 加异步套接字select函数 *捕获* *USB* *插拔* *事件* \_ *netlink* *usb*](https://blog.csdn.net/qq_45649553/article/details/144449886)
7-13[Linux中 *使用* udev来管理热 *插拔*,*使用* *netlink* 监听udev的消息可以为用户空间提供管理策略,通过解析消息中的字符串来完成控制逻辑。 *USB* 的热 *插拔* 应用广泛,比如U盘、手机、 *USB* 网卡等等,*netlink* *捕获* 消息后,解析消息中的字符串可以进一步识别是哪种设备,从而在用户空间完成逻辑控制 一、整体框架 socket s;...fd\_set set;while...](https://blog.csdn.net/qq_45649553/article/details/144449886)[go语言实现通过 *netlink* 监控 *usb* 热 *插拔* (附完整源码)\_go语言如何做到实时...](https://blog.csdn.net/it_xiangqiang/article/details/147076117)
7-14[go语言实现通过 *netlink* 监控 *usb* 热 *插拔* 监控 *USB* 热 *插拔* *事件* 在 Linux 系统中通常通过监听 *Netlink* 套接字上的 udev *事件* 来实现。以下是一个 *使用* Go 语言通过 *Netlink* 监听 *USB* 热 *插拔* *事件* 的完整示例代码。这个程序会持续运行,并在检测到 *USB* 设备的插入或移除时输出相关信息。](https://blog.csdn.net/it_xiangqiang/article/details/147076117)[通过 *netlink* *获取* 内核信息捕捉 *USB* 设备 *插拔* 消息](https://blog.csdn.net/qq_44488261/article/details/120022844)
[qq\_44488261的博客](https://blog.csdn.net/qq_44488261)
08-31 1080[Linux中,通过 *netlink* 接收内核消息,获得设备变化的消息,并输出 #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <linux/ *netlink*.h> #include <unistd.h> static int init\_hotplug\_sock(void) { struct sockaddr\_nl snl; const int](https://blog.csdn.net/qq_44488261/article/details/120022844)[Linux 下 *使用* *netlink* 检测设备的热 *插拔*](https://blog.csdn.net/qq_41630102/article/details/107307680)
[SauryN的博客](https://blog.csdn.net/qq_41630102)
07-13 1979[*使用* *netlink* 实现设备热 *插拔*](https://blog.csdn.net/qq_41630102/article/details/107307680)[linux- c检测 *USB* /SD卡热 *插拔* (*netlink*)\_ *netlink* sd卡](https://blog.csdn.net/ding283595861/article/details/107661121)
7-24[linux- c检测 *USB* /SD卡热 *插拔* (*netlink*) 可以参考: \*\* https://blog.csdn.net/u013566722/article/details/78806217 拔插 *USB* 或者SD卡,系统会打印相关的log信息,recvmsg 就会 *捕获* 到,然后解析相应的关键字段信息来判断 *usb* 或者sd卡是否拔掉或者插入。 比如:sd卡拔插 *事件* 收到后,可以解析buf,解析方法如下:...](https://blog.csdn.net/ding283595861/article/details/107661121)[*USB* 热 *插拔* 消息 *获取* 与 *NetLink* 机制](https://blog.csdn.net/martingang/article/details/8194535)
7-23[*netlink* 机制-实现系统调用 *netlink* 机制-总结 PF\_ *NETLINK* 应用实例 *NETLINK* \_KOBJECT\_UEVENT具体实现--udev实现原理 linux 内核与用户空间通信之 *netlink* *使用* 方法 如下是我实现的从内核中 *获取* *USB* 热 *插拔* 消息的代码,可根据对消息字符串的解析来定义对应的操作。事实上这种方法并不足够好(胜在简便)。比较好的做法是实现点对点...](https://blog.csdn.net/martingang/article/details/8194535)[在.NET中探测U盘的插入/拔出](https://blog.csdn.net/weixin_30731287/article/details/95704068)
[weixin\_30731287的博客](https://blog.csdn.net/weixin_30731287)
07-25 136 [有同学向我问这个问题,于是就Google了一下找到答案,不过是C下的,我将其改编成了C#的。 当设备被插入/拔出的时候,WINDOWS会向每个窗体发送WM\_DEVICECHANGE 消息,当消息的wParam 值等于 DBT\_DEVICEARRIVAL 时,表示Media设备被插入并且已经可用;如果wParam值等于DBT\_DEVICEREMOVECOMPLETE,表示Media设备已经...](https://blog.csdn.net/weixin_30731287/article/details/95704068)[...从内核 *获取* PCI主板上的 *USB* 热 *插拔* 信息\_ *netlink* *获取* pci](https://blog.csdn.net/qq_16542775/article/details/88553527)
8-3[本文详细介绍了在Linux操作系统中如何利用内核功能实现对PCI主板上 *USB* 设备的热 *插拔* 管理,重点探讨了如何 *获取* 并处理 *USB* 设备的热 *插拔* *事件* 。 摘要生成于C知道,由 DeepSeek-R1 满血版支持,前往体验 > Linux下热 *插拔* 功能: #include<stdio.h> #include<stdlib.h>...](https://blog.csdn.net/qq_16542775/article/details/88553527)[linux下检测U盘插入并读取文件\_ *netlink* u盘插入](https://blog.csdn.net/mianhuantang848989/article/details/46379267/)
7-28[获得U盘的插入或者拔取得信息的传统方法是在内核级运行hotplug程序,相关参数通过环境变量传递过来,再由hotplug通知其他关注hotplug的应用程序。这样的做法效率有些低,现在通过一种特殊类型的socket *netlink* 实现 *获取* U盘拔插的信息。 *netlink* 专门用于内核空间和用户空间的异步通信。](https://blog.csdn.net/mianhuantang848989/article/details/46379267/)[Linux *使用* *Netlink* *捕获* *USB* 热 *插拔* *事件*](https://blog.csdn.net/zt18786458319/article/details/139673452)
[zt18786458319的博客](https://blog.csdn.net/zt18786458319)
06-14 742[在 Qt 中 *使用* *Netlink* 来 *捕获* *USB* 热 *插拔* *事件* 需要结合 Qt 的 *事件* 循环机制和 *Netlink* 的底层接口。 *Netlink* 是 Linux 内核和用户空间之间的一种通信机制,适用于 *捕获* 内核 *事件* (例如 *USB* 设备的 *插拔* *事件* )。以下是一个 *使用* Qt 和 *Netlink* *捕获* *USB* 热 *插拔* *事件* 的示例。](https://blog.csdn.net/zt18786458319/article/details/139673452)[RTL8198D 网口 *插拔* *事件* *捕获* 功能实现](https://blog.csdn.net/wgl307293845/article/details/118785261)
[wgl307293845的博客](https://blog.csdn.net/wgl307293845)
07-16 1040[功能描述 路由设备网口有网线接入或者拔掉的时候通知应用层,然后在应用层做响应的处理 应用层修改 应用层去 *捕获* KOBJ\_ADD和KOBJ\_REMOVE *事件* 即可,实例代码如下 参考链接: *Netlink* 实现热拔插监控\_不积跬步,无以至千里-CSDN博客 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include...](https://blog.csdn.net/wgl307293845/article/details/118785261)[linux 监测 设备热拔插](https://turingevo.blog.csdn.net/article/details/106736416)
[TuringEvo专栏](https://blog.csdn.net/WMX843230304WMX)
06-13 553[linux 监测 设备热拔插 这个示例是 *USB* 设备热拔插,可以稍微修改代码,符合你想要监测的设备 原理 这里是通过用户空间,接收内核的消息,提取消息有效字符,匹配想要的结果,监测 *USB* 设备热拔插!!! 编译需要 启用 c++11 支持,因为 *使用* 了正则表达式匹配 编译命令:g++ *USB* -monitor.cpp -std=c++11 -o *usb* *USB* -monitor.cpp: //--编译: // g++ *USB* -monitor.cpp -std=c++11 -o *usb* // /\* Linux](https://turingevo.blog.csdn.net/article/details/106736416)[linux查看 *USB* 运行状态,Linux下 *获取* *USB* 设备 *插拔* 状态的通知](https://blog.csdn.net/weixin_29038155/article/details/116622997)
[weixin\_29038155的博客](https://blog.csdn.net/weixin_29038155)
04-30 1504[最近遇到一个需求,要求浏览器的内嵌keyboard与 *USB* keyboard状态同步。主要就是几个特殊的功能键,shift、alt、ctrl、caps、tab等等,借鉴了一个博客:http://www.voidcn.com/article/p-sjjkjzze-cy.html,其中提供了一段 *获取* *USB* 设备的代码,自己运行过后,有一定的帮助,具体的还需要深究。代码如下:#include #inclu...](https://blog.csdn.net/weixin_29038155/article/details/116622997)[*netlink* read *事件* 的处理](https://blog.csdn.net/oHeHui1/article/details/129258106)
[我的博客](https://blog.csdn.net/oHeHui1)
02-28 181[*netlink* read *事件* 的处理](https://blog.csdn.net/oHeHui1/article/details/129258106)[sonic处理 *netlink* *事件*](https://blog.csdn.net/weixin_39094034/article/details/115325287)
[weixin\_39094034的博客](https://blog.csdn.net/weixin_39094034)
03-30 1746[sonic处理 *netlink* *事件* sonic在处理路由,接口up/down,接口地址变化,team等 *事件* 上极大的依赖内核。sonic通过监听rtnl *事件* 来响应linux *事件* 。从而感知相关信息变化。 libnl sonic *使用* libnl库来操作 *netlink* *事件* ,详细内容可以访问http://www.infradead.org/~tgr...。sonic在libnl库基础上封装了类 *NetLink* 进行 *netlink* 操作。 *NetLink* class *NetLink*: public Select](https://blog.csdn.net/weixin_39094034/article/details/115325287)[linux下 监控 *USB* 插入 *事件*](https://blog.csdn.net/sno_guo/article/details/38853341)
[
热门推荐
](https://blog.csdn.net/sno_guo/article/details/38853341)
[蓝松SDK](https://blog.csdn.net/sno_guo)
08-26 1万+[linux下 监控 *USB* #include #include #include #include #include #include #include #include #include #include static int init\_hotplug\_sock(void) { struct sockaddr\_nl snl; const int buffers](https://blog.csdn.net/sno_guo/article/details/38853341)[网络子系统63\_路由子系统处理 *netlink* *事件*](https://blog.csdn.net/u012259202/article/details/12841467)
[奔跑的Linerdx的专栏](https://blog.csdn.net/u012259202)
10-17 2466[// 路由子系统 *netlink* 控制块 1.1 static struct rt *netlink* \_link inet\_rt *netlink* \_table\[RTM\_MAX - RTM\_BASE + 1\] = { \[4\] = {.doit = inet\_rtm\_newaddr, }, \[5\] = {.doit = inet\_rtm\_deladdr, }, \[6\] = {.dumpit](https://blog.csdn.net/u012259202/article/details/12841467)[*netlink* 判断 *USB* 热 *插拔* *事件*](https://blog.csdn.net/newnewman80/article/details/8766657)
[newnewman](https://blog.csdn.net/newnewman80)
04-07 7734[做嵌入式开发,尤其在网关、路由器或者其他支持 *USB* 设备的终端上,为了提高用户体验,我们常常需要支持自动识别并挂载 *USB* 设备功能。某些应用程序,在 *使用* *USB* 设备的过程中,也希望能够侦测到 *USB* 断开 *事件* ,不至于某些工作因为 *USB* 已经不存在而白做。在Linux下,我们主要有两种办法检测 *USB* 热 *插拔* 。 第一种便是定时检查/proc/scsi/scsi文件,该文件内会按照标准格式保存着当前设备](https://blog.csdn.net/newnewman80/article/details/8766657)[linux *获取* 优盘信息](https://blog.csdn.net/ZHANG_TIMI/article/details/114745599)
[1252661442的博客](https://blog.csdn.net/ZHANG_TIMI)
03-13 562[这段时间做liveCD优盘管控,需要对优盘信息进行注册管理,所以就要拿到优盘的指纹信息 cat /proc/scsi/ *usb* -storage/\* 例子: root@deepin:~# cat /proc/scsi/ *usb* -storage/\* Host scsi3: *usb* -storage Vendor: General Product: *USB* Flash Disk Serial Number: 04YRD8F50M4ONAPE Protocol: Tr...](https://blog.csdn.net/ZHANG_TIMI/article/details/114745599)[linux *usb* *事件*,Linux下实现 *USB* 口的热 *插拔* *事件* 触发](https://blog.csdn.net/weixin_39658716/article/details/116911904)
[weixin\_39658716的博客](https://blog.csdn.net/weixin_39658716)
05-13 439[目前要做一个在嵌入式平台上的 *USB* 口的热 *插拔* *事件* 。经过我现在的分析总结目前有如下方法:1,定时检查/proc/scsi/scsi文件此方法只能在PC上,但在嵌入式平台上不可用。2, *netlink* 方式 *使用* *netlink*.#include #include #include #include #include #include #include #include #include #include #...](https://blog.csdn.net/weixin_39658716/article/details/116911904)[通过 *NETLINK* \_KOBJECT\_UEVENT *捕获* udev的uevent](https://blog.csdn.net/wq897387/article/details/124188153)
[wq897387的专栏](https://blog.csdn.net/wq897387)
04-15 1148[测试代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <linux/types.h> #include <linux/ *netlink*..](https://blog.csdn.net/wq897387/article/details/124188153)[*netlink* *usb* *插拔*](https://wenku.csdn.net/answer/67815mn9ju)
07-29[*Netlink* 是一个用于Linux内核中的通信机制。通过 *Netlink* 机制,用户空间进程可以与内核空间进行通信,实现内核与用户空间之间的数据交换。而 *USB* *插拔* 则是指插入或拔出 *USB* 设备。 在Linux系统中,当用户将 *USB* 设备插入计算机时,内核会检测到 *USB* 设备的插入 *事件* ,并将此 *事件* 通过 *Netlink* 机制发送给用户空间。用户空间的 *Netlink* 监听进程可以接收到这个 *插拔* *事件* ,并进行相应的处理。 例如,当用户插入一个 *USB* 存储设备时,内核可以通过 *Netlink* 发送一个消息给用户空间的监听进程,消息中包含有关插入设备的信息,例如设备的路径、设备的供应商ID和产品ID等。用户空间的监听进程可以根据这些信息执行特定的操作,例如自动挂载存储设备,或更新相关设备列表等。 同样,当用户将 *USB* 设备拔出时,内核也会检测到拔出 *事件* ,并通过 *Netlink* 发送消息给用户空间的监听进程。监听进程可以根据收到的消息进行相应的操作,例如卸载存储设备、更新设备列表等。 总之, *Netlink* 机制为 *USB* 设备的 *插拔* 提供了一种可靠的通信机制,使内核和用户空间能够及时地进行信息交换,实现对 *USB* 设备 *插拔* *事件* 的处理。](https://wenku.csdn.net/answer/67815mn9ju)
实付 元
[使用余额支付](https://blog.csdn.net/yangchao315/article/details/)
点击重新获取
扫码支付
钱包余额 0
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。
[余额充值](https://i.csdn.net/#/wallet/balance/recharge)
举报
[ 点击体验 DeepSeekR1满血版](https://ai.csdn.net/?utm_source=cknow_pc_blogdetail&spm=1001.2101.3001.10583) 
程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!
客服 返回顶部
[](https://www.jianshu.com/u/184d9cf3e988)
[苍蝇的梦](https://www.jianshu.com/u/184d9cf3e988) IP属地: 福建
字数 805 阅读 7,082
2019-06-10 遇到的一点小问题 新需求是在U盘插入设备时实现自动挂载功能,一般都是推荐使用 [udev](https://links.jianshu.com/go?to=https%3A%2F%2Fzh.wikipedia.org%2Fwiki%2FUdev) 。记录一下第一次使用出现的问题。
###### .
刚开始先按 [网上找的方法](https://links.jianshu.com/go?to=https%3A%2F%2Fwww.ibm.com%2Fdeveloperworks%2Fcn%2Flinux%2Fl-cn-udev%2F) ,在 `/etc/udev/rules.d/` 创建个*.rules* 文件,再根据插入动作调用*.sh* 文件来执行 *[mount](https://www.jianshu.com/p/3abfdf7dd21f)* 操作:
```bash KERNEL=="sd[a-z]*",ACTION=="add",RUN+="/srv/wannoo.sh %k"
|
语法挺简单的,就是容易遇坑:有一次 KERNEL 和 ACTION 顺序弄反,然后就执行失败;还有一U盘只能读到sdd,所以 KERNEL==”sd[a-z][1-9]“ 读不到,为了兼容只能改成 KERNEL==”sd[a-z] “*;然后换行也要注意;还有就是一行命令数限制五个,多了后面的不生效。
不过虽然把语法弄懂了,但mount还是出错了:
1 2 3 4 5 6 7 8
| mount: /tmp/sdc1: permission denied. echo $? == 32
FUSE exfat 1.3.0 fusermount: mount failed: Operation not permitted echo $? == 1
WARN: volume was not unmounted cleanly.
|
.
测了几次,依然没有解决。只好再到 ArchLinux的wiki 上面仔细看看 udev (简体中文) 。按说明修改了 /etc/systemd/system/systemd-udevd.service 文件,也按要求 把挂载动作放在 udev 规则内部 ,可惜测试了还是不行。也按这篇 Auto-mounting USB storage with udev 的示例试了一下,依旧失败返回 fusermount: mount failed: Operation not permitted 。
1
| KERNEL=="sd[a-z]*",ACTION=="add",RUN+="/bin/mkdir /tmp/%k",RUN+="bin/mount -r /dev/%k /tmp/%k"
|
.
因为 udev (简体中文) 写的翻译时间是 2017-10-19 ,有点旧了,所以又仔细看了看 udev英文文档 。发现里面使用的示例不是 bin/mount 而是使用 /usr/bin/systemd-mount 去挂载。
1
| ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media"
|
在控制台试了下 systemd-mount命令 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| [root@archlinux ~] Failed to start transient mount unit: Unit media-sdb2.mount already exists. [root@archlinux ~] Stopped unit media-sdb2.mount for mount point: /media/sdb2 [root@archlinux ~] Started unit media-sdb2.mount for mount point: /media/sdb2 [root@archlinux ~] * media-sdb2.mount - /media/sdb2 Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient) Transient: yes Active: active (mounted) since Tue 2019-06-11 08:55:28 UTC; 32s ago Where: /media/sdb2 What: /dev/sdb2 Tasks: 1 (limit: 4915) Memory: 2.5M CGroup: /system.slice/media-sdb2.mount \`-10153 /usr/bin/mount.exfat /dev/sdb2 /media/sdb2 -o rw
Jun 11 08:55:27 archlinux systemd[1]: Mounting /media/sdb2... Jun 11 08:55:28 archlinux systemd[1]: Mounted /media/sdb2. # echo $? == 0
|
测试中发现加上 --automount=yes 选项之后,如果使用 umount 命令 去卸载, df 能看出成功,但是再 cd 进入之前挂载的文件夹又会自动挂载起来,所以卸载动作需要使用 systemd-umount 命令 或 systemd-mount -u 命令 去卸载。
最后,在**.rules** 文件里使用 systemd-mount 命令试一下挂载U盘。
1
| ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", RUN{program}+="/bin/mkdir /media/%k" ,RUN{program}+="/usr/bin/systemd-mount --no-block --collect $devnode /media/%k"
|
有一个U盘成功了,但有一个U盘一直没看到挂载成功,所以又用控制台试了一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| [root@archlinux ~] Started unit media-sdb2.mount for mount point: /media/sdb2 [root@archlinux ~] Job for media-sdb2.mount failed. See "systemctl status media-sdb2.mount" and "journalctl -xe" for details. [root@archlinux media] * media-sdb2.mount - /media/sdb2 Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient) Transient: yes Active: failed (Result: exit-code) since Tue 2019-06-11 08:48:38 UTC; 5s ago Where: /media/sdb2 What: /dev/sdb2
Jun 11 08:48:38 archlinux systemd[1]: Mounting /media/sdb2... Jun 11 08:48:38 archlinux mount[5851]: mount: /media/sdb2: unknown filesystem type 'exfat'. Jun 11 08:48:38 archlinux systemd[1]: media-sdb2.mount: Mount process exited, code=exited, status=32/n/a Jun 11 08:48:38 archlinux systemd[1]: media-sdb2.mount: Failed with result 'exit-code'. Jun 11 08:48:38 archlinux systemd[1]: Failed to mount /media/sdb2. [root@archlinux ~] ...
|
加上 --no-block 可以异步等待结果,但现在并不需要,所以去掉后重试。马上返回失败信息了,然后根据提示使用 systemctl status media-sdb2.mount 查看状态及记录,才知道是缺少 exfat 支持,这个问题之前在其他设备上 monut 时有遇到过,使用 pacman -Sy exfat-utils 安装后,重新拔插U盘再试了一次:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [root@archlinux media]# systemctl status media-sdb2.mount * media-sdb2.mount - /media/sdb2 Loaded: loaded (/run/systemd/transient/media-sdb2.mount; transient) Transient: yes Active: activating (mounting) since Tue 2019-06-11 08:50:36 UTC; 93ms ago Where: /media/sdb2 What: /dev/sdb2 Cntrl PID: 7177 (mount) Tasks: 2 (limit: 4915) Memory: 2.5M CGroup: /system.slice/media-sdb2.mount |-7177 /usr/bin/mount /dev/sdb2 /media/sdb2 \`-7178 /usr/bin/mount.exfat /dev/sdb2 /media/sdb2 -o rw
Jun 11 08:50:36 archlinux systemd[1]: Mounting /media/sdb2... # echo $? == 3
|
不懂为什么返回值是3。使用 df 看了下,已经正常挂载了。先不理会。
.
网上随便搜了几篇文章参考,这边记录一下:
使用 udev 高效、动态地管理 Linux 设备文件
在 Linux 中如何编写基本的 udev 规则
An introduction to Udev: The Linux subsystem for managing device events
udev学习笔记汇总
关于 udevadm命令 ,有用到几个先记录一下:
1 2 3 4 5 6
| udevadm monitor
udevadm test --action="add" /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.3/1-2.3:1.0/host3/target3:0:0/3:0:0:0/block/sdd
udevadm control --reload
|
然后有几个会用到的位置也记一下:
1 2 3 4
| /usr/lib/udev/rules.d /etc/udev/rules.d/ /usr/lib/systemd/system/systemd-udevd.service /etc/systemd/system/systemd-udevd.service
|
https://wiki.archlinux.org/index.php/Udisks_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
0人点赞
Linux
更多精彩内容,就在简书APP
“小礼物走一走,来简书关注我”
还没有人赞赏,支持一下

苍蝇的梦 路走对了,就不怕远
总资产9 共写了4.4W字 获得127个赞 共30个粉丝
赞 1赞
赞赏

手机看全文