总结
这篇先大概对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》