Linux之设备管理器及热插拔处理
Linux之设备管理器及热插拔处理
前言
Linux内核设备管理器主要来管理/dev
中的设备节点,并在添加或删除设备时处理所有用户空间操作,比如U盘SD卡等热插拔的处理–自动挂载与卸载。
Linux内核设备管理器主要有mdev
,udev
和eudev
等,今天就简单来看看它们。
- mdev是udev的简化版本,是busybox的一部分,最适合用在简单的嵌入式系统,使用
busybox
的地方。 - udev是systemd的设备管理器,相对mdev来说要复杂些,一般用在PC上的linux或比较高端点的嵌入式系统,使用
systemd
的地方。 - eudev是
udev
的fork版本,所以很多规则这些都是和udev类似,主要是为了独立于systemd等initx系统和Linux发行版。
udev
和 mdev
是两个使用 uevent 机制处理热插拔问题的用户空间程序,两者的实现机理不同。
udev
基于 netlink 机制mdev
基于 uevent_helper 机制
每当设备状态发生变化时,内核都会发出一个 uevent 事件,设备管理器会接收到该事件,根据 uevent 中包含的信息,会去匹配触发制定的规则并执行所需的操作,包括创建或删除设备文件,触发将特定固件文件加载到内核内存中,执行相应的脚本等等。
具体的实现原理就深入展开了,这里只介绍些简单的概念,感兴趣的同学可以去研究下源码。
mdev
mdev源码:https://github.com/mirror/busybox/blob/master/util-linux/mdev.c
busybox官网:http://www.busybox.net/source.html
更多详情可查看上面的源码。
"mdev -s"
会扫描 /sys/class/xxx
,查找包含dev文件的目录,然后mdev
会创建 /dev/device_name
节点。
当设备状态发生变化时,比如热插拔,mdev 会去匹配设定的相关规则,去做相应的处理,比如创建节点时,修改节点权限,执行相应命令等。
下面来看看 mdev 的有关规则
mdev规则
格式如下:
<device regex> <uid>:<gid> <octal permissions> [<@$*><cmd>]
后面操作说明:
=xxx/
: 移动到/dev/xxx
>xxx/yyy%1
: 移动到/dev/xxx/yyyN
,并创建符号链接到/dev/yyyN
@
: 创建节点后执行后面的$
: 删除节点前执行后面的*
: 创建后和删除前都运行后面的
默认规则文件为:/etc/mdev.conf
。
简单示例
规则例子:
mice 0:0 0660 =input/
mouse.* 0:0 0660 =input/
event.* 0:0 0660 =input/
pcm.* 0:0 0660 =snd/
control.* 0:0 0660 =snd/
timer 0:0 0660 =snd/
$DEVNAME=bus/usb/([0-9]+)/([0-9]+) 0:0 0660 =bus/usb/%1/%2
sd[a-z][0-9]+ 0:0 666 * /etc/usb/usb_hotplug.sh
sd[a-z] 0:0 666 * /etc/usb/usb_hotplug.sh
mmcblk[0-9]p[0-9] 0:0 660 @/etc/hotplug/sdcard_insert
mmcblk[0-9] 0:0 660 $/etc/hotplug/sdcard_remove
U盘热插拔一个简单脚本/etc/usb/usb_hotplug.sh
:
#!/bin/sh
if [ $ACTION = "add" ]; then
if [ ${#DEVNAME} -eq 3 ];then
sleep 1
fi
mkdir -p /vendor/udisk_$DEVNAME
mount -o iocharset=utf8 /dev/$DEVNAME /vendor/udisk_$DEVNAME
if [ $? -ne 0 ];then
rm -rf /vendor/udisk_$DEVNAME
fi
else
umount /vendor/udisk_$DEVNAME
if [ $? -eq 0 ];then
rm -rf /vendor/udisk_$DEVNAME
fi
fi
udev与eudev
udev与eudev使用上比较类似,这里就放在一起了。
udev源码: https://cgit.freedesktop.org/systemd/systemd/tree/src/udev
eudev源码: https://github.com/eudev-project/eudev
eudev is a standalone dynamic and persistent device naming support (aka userspace devfs) daemon that runs independently from the init system. eudev strives to remain init system and linux distribution neutral. It is currently used as the devfs manager for more than a dozen different linux distributions.
This git repo is a fork of git://anongit.freedesktop.org/systemd/systemd with the aim of isolating udev from any particular flavor of system initialization. In this case, the isolation is from systemd.
This is a project started by Gentoo developers and testing was initially being done mostly on OpenRC. We welcome contribution from others using a variety of system initializations to ensure eudev remains system initialization and distribution neutral. On 2021-08-20 Gentoo decided to abandon eudev and a new project was established on 2021-09-14 by Alpine, Devuan and Gentoo contributors (alphabetical order).
udev规则
默认规则文件:
/etc/udev/rules.d/
/lib/udev/rules.d
上面的目录中带有很多设备默认的配置规则,大家可以根据自己的需求去研究和修改。
简单示例
一个SD卡热插拔的规则配置例子:/lib/udev/rules.d/61-sd-cards-auto-mount.rules
KERNEL!="mmcblk*[0-9]", GOTO="sd_cards_auto_mount_end"
SUBSYSTEM!="block", GOTO="sd_cards_auto_mount_end"
ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="sd_cards_auto_mount_end"
ATTRS{type}!="SD", GOTO="sd_cards_auto_mount_end"
IMPORT{program}="/sbin/blkid -o udev -p %N"
ACTION=="add", ENV{mount_options_vfat}="rw,uid=1000,gid=1000,dmask=022,fmask=133,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat", RUN+="/bin/mount -t vfat -o %E{mount_options_vfat} /dev/%k '/mnt/sdcard'"
ACTION=="add", ENV{mount_options_ntfs}="rw,uid=1000,gid=1000,dmask=022,fmask=133,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="ntfs", RUN+="/bin/mount -t ntfs-3g -o %E{mount_options_ntfs} /dev/%k '/mnt/sdcard'"
ACTION=="add", ENV{mount_options_exfat}="rw,uid=1000,gid=1000,dmask=022,fmask=133,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="exfat", RUN+="/bin/mount -t exfat-fuse -o %E{mount_options_exfat} /dev/%k '/mnt/sdcard'"
ACTION=="add", ENV{mount_options_ext2}="users,exec,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="ext2", RUN+="/bin/mount -t ext2 -o %E{mount_options_ext2} /dev/%k '/mnt/sdcard'"
ACTION=="add", ENV{mount_options_ext3}="users,exec,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="ext3", RUN+="/bin/mount -t ext3 -o %E{mount_options_ext3} /dev/%k '/mnt/sdcard'"
ACTION=="add", ENV{mount_options_ext4}="users,exec,noatime"
ACTION=="add", ENV{ID_FS_TYPE}=="ext4", RUN+="/bin/mount -t ext4 -o %E{mount_options_ext4} /dev/%k '/mnt/sdcard'"
ACTION=="remove", RUN+="/bin/umount '/mnt/sdcard'"
LABEL="sd_cards_auto_mount_end"