linux udev


原文链接: linux udev

https://www.cnblogs.com/fah936861121/p/6496608.html

udevadm info -a -p $(udevadm info -q path -n /dev/sg2)

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查看)
2.2.4 udev 的值和可调用的替换操作符

在键值对中的键和操作符都介绍完了,最后是值 (value)。Linux 用户可以随意地定制 udev 规则文件的值。例如:my_root_disk, my_printer。同时也可以引用下面的替换操作符:

$kernel, %k:设备的内核设备名称,例如:sda、cdrom。
$number, %n:设备的内核号码,例如:sda3 的内核号码是 3。
$devpath, %p:设备的 devpath路径
$id, %b:设备在 devpath里的 ID 号。
$sysfs{file}, %s{file}:设备的 sysfs里 file 的内容。其实就是设备的属性值。
例如:$sysfs{size} 表示该设备 ( 磁盘 ) 的大小。
$env{key}, %E{key}:一个环境变量的值。
$major, %M:设备的 major 号。
$minor %m:设备的 minor 号
$result, %c:PROGRAM 返回的结果。
$parent, %P:父设备的设备文件名。
$root, %r:udev_root的值,默认是 /dev/
$tempnode, %N:临时设备名。
%%:符号 % 本身。
$$:符号 $ 本身。

###
/etc/udev/rules.d/

SUBSYSTEMS=="scsi",ATTR{vendor}=="Generic",ATTR{max_sectors}=="240",ATTR{max_sectors}="2048"
KERNEL=="sd[a-z]*", SUBSYSTEMS=="usb", ATTRS{idProduct}=="0769",ATTRS{idVendor}=="05e3",RUN+="/bin/rm -fr /dev/%k"
KERNEL=="sg[0-9]", SUBSYSTEMS=="usb", ATTRS{idProduct}=="0769", ATTRS{idVendor}=="05e3", MODE="0666", OPTIONS+="last_rule"

OPTIONS选项
另外一个有用的赋值是OPTIONS列表. 不多的可用的选项有:
all_partitions - 为一个块设备创建所有可能的分区, 而不是初始检测到的那些分区.
ignore_device - 完全忽略事件.
last_rule - 确保后面的所有规则不会有效.
例如, 下面规则设置我的硬盘节点的组所有权,并且后面的规则对它没有任何效果:
KERNEL=="sda", GROUP="disk", OPTIONS+="last_rule"

1.利用udev自动挂载usb设备

KERNEL!="sd[b-z]?", GOTO="automount_exit"
# 检测add事件 
ACTION=="add", SUBSYSTEM=="block", RUN+="/bin/mkdir /media/%E{ID_FS_LABEL}-%E{ID_FS_UUID}", RUN+="/bin/mount -o uid=1000,user,codepage=936,utf8 $root/%k /media/%E{ID_FS_LABEL}-%E{ID_FS_UUID}"

ACTION=="remove", SUBSYSTEM=="block", RUN+="/bin/umount /media/%E{ID_FS_LABEL}-%E{ID_FS_UUID}", RUN+="/bin/rmdir /media/%E{ID_FS_LABEL}-%E{ID_FS_UUID}"

LABEL="automount_exit"

保存为 /etc/udev/rules.d/ 下的某个文件。

第一行用 glob 跳过名称非 sd[b-z]? 字样的。

%E{ID_FS_LABEL} 是卷标,%E{ID_FS_UUID} 是 UUID,
第二行就是检测 add 事件,先根据卷标和 UUID 在 /media/下创建一个目录然后挂载。

第三行是相应的卸载命令。

二、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下面

/etc/udev/rules.d/$ ls
hwdb.d rules.d udev.conf

其中udev.conf是udev默认的配置文件。
用户自定义的配置文件在rules.d文件下。
在rules.d目录下新建10-usb.rules。其中内容如下:

ACTIONS=="add",KERNEL=="sdd1",SUBSYSTEMS=="block",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
1
结果如图

/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

版权声明:本文为CSDN博主「lzylzy112233」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lzylzy112233/article/details/84997466

`