Ubuntu之udev用法总结
一、udev简介
u即user space,dev是device,通过它的名字,我们就可以简单了解到,它是一个和用户态相关的驱动设备管理机制。udev是一个针对2.6内核的文件系统。提供一种基于用户空间的动态设备节点管理和命名的解决方案。用于取代落后的devfs
udev与硬件平台无关,属于用户空间的进程,是一个后台程序,它脱离驱动层的关联,而建立在操作系统之上,只要修改配置文件使之生效,无需重启操 作系统,它需要sysfs的支持,当底层设备发生插拔的时候,底层驱动通过netlink发送事件(uevent)给udev后台程序,udev监听这些 事件,并在上层做相应的设备节点的创建,命名,权限控制等。
它有以下优点:
1.动态管理:当设备添加/删除时,udev的守护进程侦听到来自内核的uevent,以此添加或者删除/dev下的设备文件,所以,udev只为 已经连接的设备产生设备文件,而不会在/dev/下产生大量虚无的设备文件.在发生热插拔时,设备的变化的相关信息会输出到内核的/sys(sysfs文 件系统),udev利用sysfs的信息来进行相应的设备节点的管理
2.自定义命名规则:通过规则文件,udev在/dev/下为所有的设备定义了内核设备名称,比如/dev/sda,/dev/hda,/dev /fd(这些都是驱动层定义的设备名)等等。由于udev是在用户空间运行,Linux用户可以自己定义规则文件,产生标识性强的设备文件,比如/dev /boot_disk,/dev/root_disk,/dev/color_printer等等
3.设定设备的权限和所有者/组。同样在规则文件中,可以自己定义设备相关的权限和所有者/组。
(详细说明可以通过man udev查看)
二、udev使用例子,解决多个设备插拔造成设备号变化的问题
Ubuntu连接多个设备,或这重复插拔设备的时候,识别出的设备号会变化。例如反复插U盘,识别出的设备号可能是/dev/sdb,/dev/sdc,/dev/sdd…(硬盘始终是/dev/sda)
网上之前的博客中可以利用udev直接修改U盘等设备的设备号,尝试了一下会出错,百度发现是udev后续版本去掉了这个功能。
目前思路是建立设备的链接,固定链接的名称,后续可以通过固定的链接(link)来操作设备。步骤如下:
1.先插入U盘,通过sudo fdisk -l 观察到的U盘信息如下:
Device Boot Start End Sectors Size Id Type
/dev/sdd1 256 56062207 56061952 26.8G c W95 FAT32 (LBA)
/dev/sdd4 * 56062208 60062499 4000292 1.9G 16 Hidden FAT16
(这里看到U盘的Boot分区分配了1.9G,不科学啊)
2.编写Udev配置文件
udev的配置文件在/etc/udev下面
lzy@lzy-Inspiron-3847:/etc/udev$ ls
hwdb.d rules.d udev.conf
其中udev.conf是udev默认的配置文件。用户自定义的配置文件在rules.d文件下。
在rules.d目录下新建10-usb.rules。其中内容如下:
KERNEL=="sdd1",SUBSYSTEMS=="block",ACTIONS=="add",SYMLINK+="USB1_link"
简单介绍一下上面的语法:
Udev中,双等号为判断,+=,:=,=均为“赋值操作”。
以上有三个判断条件:
ACTIONS==“add”——插入设备
KERNEL==“sdd4”——设备号为/dev/sdd4
SUBSYSTEMS==“block”——设备类型为“块设备”
如果满足上述三个条件,则将创建此设备的软链接USB1_link.
3.Kernel和subsystems查询方法
其中kernel和subsystems信息,可以通过udevadm命令查询
例如,如下命令查询sdd的U盘信息
udevadm info -a -p /sys/block/sdd
其中sdd的信息如下(可以查询到sdd的Kernel和SUBSYSTEM信息):
looking at device '/devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/host6/target6:0:0/6:0:0:0/block/sdd':
KERNEL=="sdd"
SUBSYSTEM=="block"
DRIVER==""
...
我们需要知道的是sdd1(U盘中的具体盘符的信息),需要通过如下方法获取。
下列命令获取sdd1设备的设备目录
udevadm info -q path -n /dev/sdd1
输出如下:
/devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/host6/target6:0:0/6:0:0:0/block/sdd/sdd1
将上面的一串作为早先udevadm info -a -p命令的输入路径,即这样写:
udevadm info -a -p $(udevadm info -q path -n /dev/sdd1)
输出最开头的结果路下:
looking at device '/devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/host6/target6:0:0/6:0:0:0/block/sdd/sdd1':
KERNEL=="sdd1"
SUBSYSTEM=="block"
DRIVER==""
...
4.使得udev文件生效的方法
通常,使得配置后的文件生效,需要采用热插拔的方法更新udev规则,不过有更简单的方法如下:
sudo udevadm test /sys/class/block/sdd1
结果如图
lzy@lzy-Inspiron-3847:/etc/udev/rules.d$ ls -al /dev/USB1*
lrwxrwxrwx 1 root root 4 12月 14 09:51 /dev/USB1_link -> sdd1
5.其他注意事项
1.如果在10-usb.rules中加入语句NAME+=“string”,则执行更新命令的时候,会有如下error:
NAME="lzy_USB3" ignored, kernel device nodes can not be renamed; please fix it in /etc/udev/rules.d/10-local.rules:1
经查是udev后续版本不再支持直接修改设备号。
2.本例子中udev的设备是通过设备号sdd1来识别的,其实该设备号每次插拔的时候都有变化,可以设置其他参数匹配对应的硬件,来保证对应设备接入之后,生成对应的硬件。
参考博客
[1] https://blog.csdn.net/fjb2080/article/details/4876314
[2] http://www.cnblogs.com/cslunatic/p/3171837.html
[3]https://blog.csdn.net/qq_29729577/article/details/50825134