嵌入式Linux基于udev原则自动挂载U盘或sd卡

我们在开发嵌入式产品时,会需要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为好。


欢迎转载,欢迎指正,更欢迎点赞。转载请附原文链接。

嵌入式Linux基于udev原则自动挂载U盘或sd卡

上一篇:关于Excel文件导入到Sqlserver2008中出现截断错误的解决办法


下一篇:在Ubuntu安装IDEA图形界面