总结
这篇先大概对udev的应用有个大概的,简单的了解,具体的一些分析或者其他更深入的一些其他用法,以后有空可以再分析
简介
udev是Linux(linux2.6内核之后)默认的设备管理工具。udev 以守护进程的形式运行,通过侦听内核发出来的uevent来管理 /dev目录下的设备文件。通过udev编写对应规则,实现设备节点变化时做出规定的动作。例如下面要介绍的热插拔实验。

另外,在嵌入式系统中,也可以用udev的轻量级版本mdev,mdev集成与busybox中。Android也没有采用udev,采用的是vold,不过机制跟udev是一样的。
应用
场景
假设现在插入U盘,从图中打印其分区为sdb,这时候我想自动挂在 /mnt/usb下

这时候可以利用udev相关的规则,来创建一个U盘插入规则。
U盘插入规则
在/etc/udev/rules.d目录下添加一个文件,叫做11-add-usb.rules ,用于检测U盘插入规则(add)
vi /etc/udev/rules.d/11-add-usb.rules

在11-add-usb.rules中添加如下内容:
ACTION!="add",GOTO="END"
KERNEL=="sdb[0-9]",RUN+="/etc/mount-usb.sh %k"
LABEL="END"

其中RUN+="/etc/mount-usb.sh %k"需要我们在/etc下相关的U盘挂载规则,也就是我们一开始想实现的:自动挂载到某个固定的路径下。在 /etc 下添加脚本
vi /etc/mount-usb.sh

脚本内容如下
#!/bin/sh
if [ ! -d "/mnt/usb" ]; then
mkdir -p /mnt/usb
fi
mount -t vfat /dev/$1 /mnt/usb
sync

给脚本加权限,chmod +x /etc/mount-usb.sh

卸载规则
同理自动卸载
vi /etc/udev/rules.d/11-remove-usb.rules

在11-remove-usb.rules中添加如下内容:
ACTION!="remove",GOTO="END"
KERNEL=="sdb[0-9]",RUN+="/etc/umount-usb.sh %k"
LABEL="END"

然后在/etc目录下创建umount-usb.sh脚本,给脚本加权限
vi /etc/umount-usb.sh
chmod +x /etc/umount-usb.sh

在umount-usb.sh中添加如下内容:
#!/bin/sh
sync
umount /mnt/usb

验证时刻
插入U盘,此时进入/mnt/usb路径,可以看到U盘内的文件,说明刚刚编写的udev的add规则已经生效了

输入df查看

输入vfat查看

这时候拔出U盘,如下图所示,udev的remove规则也是生效的


规则
常用规则
基本语法
- 规则文件中以 ”#” 开头的行以及空行将被忽略
- 规则文件必须以 .rules 作为后缀名,否则将被忽略
- 规则文件分别位于: 系统规则目录
(/usr/lib/udev/rules.d)、 运行时规则目录(/run/udev/rules.d)、 本机规则目录(/etc/udev/rules.d),/etc/的优先级最高、/run/的优先级居中、/usr/lib/的优先级最低,也就是说我们可以在本机规则目录(/etc/udev/rules.d)下添加新的规则,它优先级最高,如果存有低优先级的同类规则,也会被高优先级的新规则替换掉,规则文件开头的数字越小它的执行顺序越靠前 - “键”有两种类型:匹配与赋值。 如果某条规则的所有匹配键的值都匹配成功,那么就表示此条规则匹配成功, 也就是此条规则中的所有赋值键都会被赋予指定的值。
匹配类
“==”等于“!=”不等于“ACTION”匹配事件的动作,例如"add"表示插入一个设备“KERNEL”匹配设备的内核名称,如sda“SUBSYSTEM”所属的子系统。例如"sound"或"net"等
赋值类
“=”,为键赋予指定的值“LABEL”设置一个可用作GOTO跳转目标的标签“GOTO”跳转到下一个匹配的LABEL标签所在的规则“RUN”{类型}对于每一个设备事件来说,在处理完规则之后,都可以再接着执行一个程序列表(默认为空)。 不同的”类型”含义如下"program"一个外部程序, 如果是相对路径, 那么视为相对于/usr/lib/udev目录。 否则必须使用绝对路径。如果未明确指定”类型”, 那么这是默认值。"builtin"与program类似,但是仅用于表示内置的程序。程序名与其参数之间用空格分隔。 如果参数中含有空格,那么必须使用单引号(')界定。仅可使用运行时间非常短的前台程序, 切勿设置任何后台守护进程或者长时间运行的程序
举例说明
下面分析add
ACTION!="add",GOTO="END"
KERNEL=="sdb[0-9]",RUN+="/etc/mount-usb.sh %k"
LABEL="END"
如上的内容是:如果不是add添加事件,那么就跳到END标签处结束,如果是add事件那么执行如下规则:如果添加的设备是sdb0至sdb9中任意一个,那么就执行RUN后面的内容,此处是一个脚本,一个挂载U盘的脚本,它还带有个参数%k,表示kernel的值。
同理分析remove
ACTION!="remove",GOTO="END"
KERNEL=="sdb[0-9]",RUN+="/etc/umount-usb.sh %k"
LABEL="END"
如果不是remove添加事件,那么就跳到END标签处结束,如果是remove事件那么执行以下规则:如果移出的设备是sda0至sda9中任意一个,那么就执行RUN后面的内容,此处是一个脚本,一个卸载U盘的脚本,它还带有个参数%k,表示kernel的值。
参考链接
- 《Linux设备驱动开发详解》
- 《udev 中文手册 [金步国]》
- 《Writing udev rules.html》