linux6.5 udev指的是什么

71次阅读
没有评论

共计 9630 个字符,预计需要花费 25 分钟才能阅读完成。

本篇内容介绍了“linux6.5 udev 指的是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

linux 6.5 udev 是 Linux 内核的设备管理器;它主要的功能是管理“/dev”目录底下的设备节点,它同时也是用来接替 devfs(设备文件系统)及 hotplug(热拔插)的功能;在传统的 Linux 系统中,“/dev”目录下的设备节点为一系列静态存在的文件,而“udev”则动态提供了在系统中实际存在的设备节点。

linux 6.5 udev 是什么?

udev udevadm 介绍及 linux 设备重命名和自动挂载应用实例分析

(一)UDEV 介绍

udev 在维基百科中的定义是:udev (userspace /dev) is a device manager for the Linux kernel. As the successor of devfsd and hotplug, udev primarily manages device nodes in the /dev directory. At the same time, udev also handles all user space events raised when hardware devices are added into the system or removed from it, including firmware loading as required by certain devices。用中文来说就是:udev 是 Linux 内核的设备管理器。它主要的功能是管理 /dev 目录底下的设备节点。它同时也是用来接替 devfs(设备文件系统) 及 hotplug(热拔插) 的功能,这意味着它要在添加 / 删除硬件时处理 /dev 目录以及所有用户空间的行为,包括加载 firmware 时。

(1)udev 概要:

在传统的 Linux 系统中,/dev 目录下的设备节点为一系列静态存在的文件,而 udev 则动态提供了在系统中实际存在的设备节点。虽然 devfs 提供了类似功能,但 udev 有比 devfs 更加好的地方:

udev 支持设备的固定命名,而并不依赖于设备插入系统的顺序。默认的 udev 设置提供了存储设备的固定命名。可以使用其 vid(vendor)、pid(device)、设备名称(model)等属性或其父设备的对应属性来确认某一设备。

udev 完全在用户空间执行,而不是像 devfs 在内核空间一样执行。结果就是 udev 将命名策略从内核中移走,并可以在节点创建前用任意程序在设备属性中为设备命名。

(2)udev 运行方式:

udev 是一个通用的内核设备管理器。它以守护进程的方式运行于 Linux 系统,并监听在新设备初始化或设备从系统中移除时,内核(通过 netlink socket)所发出的 uevent。
    系统提供了一套规则用于匹配可发现的设备事件和属性的导出值。匹配规则可能命名并创建设备节点,并运行配置程序来对设备进行设置。udev 规则可以匹配像内核子系统、内核设备名称、设备的物理等属性,或设备序列号的属性。规则也可以请求外部程序提供信息来命名设备,或指定一个永远一样的自定义名称来命名设备,而不管设备什么时候被系统发现.

(3)udev 系统架构:

udev 系统可以分为三个部分:

libudev 函数库,可以用来获取设备的信息。

udevd 守护进程,处于用户空间,用于管理虚拟 /dev

管理命令 udevadm,用来诊断出错情况。

系统获取内核通过 netlink socket 发出的信息。早期的版本使用 hotplug,并在 /etc/hotplug.d/default 添加一个链接到自身来达到目的。

(二)udevadm 命令介绍

在 Linux man page 中它是这么描述的。udevadm – udev management tool。也就是说 udevadm 命令是管理 udev 的一个工具。实际我们如果要实现设备的重命名或是设备的自动挂载,我们也是使用 udevadm 来查看和跟踪 udev 的信息。
    udevadm 可以用来监视和控制 udev 运行时的行为,请求内核事件,管理事件队列,以及提供简单的调试机制。

(1)udevadm 主命令:

info       查询 sysfs 或者 udev 的数据库

trigger 从内核请求 events

settle   查看 udev 事件队列,如果所有的 events 已处理则退出

control   修改 udev 后台的内部状态信息

monitor 监控内核的 uevents

hwdb     处理硬件数据库索引

test       调试

(2)命令应用:(a)查看设备信息:

udevadm info --query=all --name=sda 查询 sda 的所有信息 
udevadm info --query=path --name=sda 查看 sda 的 path
udevadm info --attribute-walk --name=/dev/nvme0n1   查看 nvme0n1 的所有父设备一直到 sysfs 的根节点

–query=type 从数据库中查询指定类型的设备。需要 –path 和 –name 来指定设备。合法的查询文件是:设备名,链接,路径,属性
–path=devpath   设备的路径
–name=file   设备节点或者链接
–attribute-walk 打印指定设备的所有 sysfs 记录的属性,以用来 udev 规则匹配特殊的设备。该选项打印链上的所有设备信息,最大可能到 sys 目录。
–device-id-of-file=file 打印主 / 从设备号
–export-db   输出 udev 数据库中的内容

(b)监控设备事件:

udevadm monitor [options] 监听内核事件和 udev 发送的 events 事件。打印事件发出的设备。可以通过比较内核或者 udev 事件的时间戳来分析事件时序。

udevadm monitor --property   输出事件的属性 
udevadm monitor --kernel --property --subsystem-match=usb     过滤监听符合条件的时间

–kernel 输出内核事件
–udev 输出 udev 规则执行时的 udev 事件
–property 输出事件的属性
–subsystem-match=string 通过子系统或者设备类型过滤事件。只有匹配了子系统值的 udev 设备事件通过。
–tag-match=string 通过属性过滤事件,只有匹配了标签的 udev 事件通过。

(c) 模拟一个 udev 事件

udevadm test [options] devpath 模拟一个 udev 事件,打印出 debug 信息。

(d) 接收内核发送来的设备事件

udevadm trigger [options] 接收内核发送来的设备事件。主要用于重放 coldplug 事件信息
(内核在启动时已经检测到了系统的硬件设备,并把硬件设备信息通过 sysfs 内核虚拟文件系统导出。udev 扫描 sysfs 文件系统,根据硬件设备信息生成热插拔(hotplug)事件,udev 再读取这些事件,生成对应的硬件设备文件。由于没有实际的硬件插拔动作,所以这一过程被称为 coldplug。)
–verbose 输出将要被触发的设备列表。
–dry-run 不真的触发事件
–type=type 触发一个特殊的设备。合法的类型:devices,subsystem,failed. 默认是 devices
–action=action 被触发的事件,默认是 change
–subsystem-match=subsystem 触发匹配子系统的设备事件。这个选项可以被多次指定,并且支持 shell 模式匹配。
–attr-match=attribute=value   触发匹配 sysfs 属性的设备事件。如果属性值和属性一起指定,属性的值可以使用 shell 模式匹配。如果没有指定值,会重新确认现有属性。这个选项可以被多次指定。
–attr-nomatch=attribute=value 不要触发匹配属性的设备事件。如果可以使用模式匹配。也可以多次指定
–property-match=property=value 匹配属性吻合的设备。可以多次指定支持模式匹配
–tag-match=property 匹配标签吻合的设备。可以多次指定。
–sysname-match=name 匹配 sys 设备名相同的设备。可以多次指定支持模式匹配。

(e) 查看 udev 事件队列

udevadm settle [options] 查看 udev 事件队列,如果所有事件全部处理完就退出。
–timeout=seconds 等待事件队列空的最大时间。默认是 180 秒。如果是 0 则立即退出。
–seq-start=seqnum   只等待到给定的顺序号。
–seq-end=seqnum 只等待到给定顺序号之前。
–exit-if-exists=file   如果文件存在就退出
–quiet 不输出任何信息

(二)应用实例:

使用 udev 实现 USB,SD 卡设备的重命名、自动挂载、自动卸载。

该功能的简单应用可以参考另外一博客《udev 重命名设备节点名 自动挂载、卸载存储设备分区》

在本文中主要记录在使用时遇到的问题以及注意事项。

(三)注意事项:(1)设备冲突问题:

在海思平台,对于有些 SD 卡或是 USB 自动挂载有些时候会出现冲突的问题,问题现象就是自动挂载的时候有时候有时候 U 盘和 SD 卡自动挂载相互干扰。主要原因点是因为海思的 HI35XX 的很多设备不具备 SDIO 总线,所以如果要使用 SD 的设备,一般都是将 SD 卡通过读卡器转换为 USB 总线信号。对于对于这类问题,可以通过 SD 卡的读卡器 ID 来区分是 USB 还是 SD 卡设备。

在海思平台可以使用下面命令查看 USB 设备信息:

lsusb:

~ # lsusb
Bus 001 Device 002: ID 1c9e:9b3c
Bus 001 Device 003: ID 05e3:0610
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0001
Bus 001 Device 008: ID 0951:1642
Bus 001 Device 009: ID 05e3:0716
Bus 001 Device 006: ID 0bda:8176
~ #

cat device

~ # cat /sys/kernel/debug/usb/devices 
T:  Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
B:  Alloc=  0/900 us (0%), #Int=  0, #Iso=  0
D:  Ver= 1.10 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0001 Rev= 3.10
S:  Manufacturer=Linux 3.10.0 ohci_hcd
S:  Product=HIUSB OHCI
S:  SerialNumber=hiusb-ohci
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=255ms

T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480  MxCh= 2
B:  Alloc=  0/800 us (0%), #Int=  5, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1d6b ProdID=0002 Rev= 3.10
S:  Manufacturer=Linux 3.10.0 ehci_hcd
S:  Product=HIUSB EHCI
S:  SerialNumber=hiusb-ehci
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=  0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   4 Ivl=256ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(ifc) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=1c9e ProdID=9b3c Rev= 3.18
S:  Manufacturer=LONGSUNG
S:  Product=USB Modem
C:* #Ifs= 5 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=option
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E:  Ad=83(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E:  Ad=85(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E:  Ad=87(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
E:  Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=GobiNet
E:  Ad=89(I) Atr=03(Int.) MxPS=   8 Ivl=32ms
E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#=  3 Spd=480  MxCh= 4
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=02 MxPS=64 #Cfgs=  1
P:  Vendor=05e3 ProdID=0610 Rev=32.98
S:  Product=USB2.0 Hub
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=01 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=256ms
I:* If#= 0 Alt= 1 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=02 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=256ms

T:  Bus=01 Lev=02 Prnt=03 Port=00 Cnt=01 Dev#=  8 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(ifc) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=0951 ProdID=1642 Rev= 1.00
S:  Manufacturer=Kingston
S:  Product=DT 101 G2
S:  SerialNumber=001CC0EC32F7BB40F71300BF
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=200mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

T:  Bus=01 Lev=02 Prnt=03 Port=02 Cnt=02 Dev#=  9 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(ifc) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=05e3 ProdID=0716 Rev=97.27
S:  Manufacturer=Genesys
S:  Product=USB Reader
S:  SerialNumber=000000000013
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

T:  Bus=01 Lev=02 Prnt=03 Port=03 Cnt=03 Dev#=  6 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(ifc) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=0bda ProdID=8176 Rev= 2.00
S:  Manufacturer=Realtek
S:  Product=802.11n WLAN Adapter
S:  SerialNumber=00e04c000001
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 4 Cls=ff(vend.) Sub=ff Prot=ff Driver=rtl8192cu
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=84(I) Atr=03(Int.) MxPS=  64 Ivl=125us
~ #

查看上面信息可以知道 USB 相关的设备有:
Product=HIUSB EHCI   #海思 USB 总线
Product=USB Modem  # 上网模块
Product=USB2.0 Hub   #USB HUB
Product=DT 101 G2    # U 盘
Product=USB Reader # usb 读卡器
Product=802.11n WLAN Adapter #USB 网卡

(2)多属性匹配问题

对于一个设备如果要匹配他的多个属性,或者是同一个属性,它在不同的层级中有不同的值,那么这个时候需要使用 GOTO 功能。比如在一个设备中要重名名一个 USB 设备,它的命令如下:

KERNEL== sd* ,KERNELS== *:0:0:1 ,ATTRS{scsi_level}== 0 ,ATTRS{product}== USB Reader ,ATTRS{idVendor}== 05e3 ,ATTRS{idProduct}== 0716 ,SYMLINK+= usbsda%n ,OPTIONS= ignore_remove 

这里涉及到多个属性 ATTRS 值的匹配,另外该 USB 因为有些经过了 usbHUB, 所以他的 idVendor 和 idProduct 有多个,就有总线的,也有 HUB 的,还有 USB 设备的,这样的情况下是匹配不上设备的。具体是什么原因我没有找到一个合理的解释,但是我又一个可用的解决方案,那就是使用 GOTO。将上面命令改成如下就可以了。

KERNEL== sd* ,KERNELS== *:0:0:1 ,ATTRS{scsi_level}== 0 GOTO= hisi_end 
ATTRS{product}== USB Reader ,ATTRS{idVendor}== 05e3 ,ATTRS{idProduct}== 0716 ,SYMLINK+= usbsda%n ,OPTIONS= ignore_remove
LABEL= hisi_end

(3)监控设备事件

udev 的一些匹配规则有些时候比较的莫名其妙,我也没有找到哪里有比较详细的说明,网上的介绍都它过于简单,实际应用的时候还是很多的问题,比如针对上面介绍的设备,如果要写一条卸载设备的命令,可以使用下面语句:

ACTION== remove ,KERNELS== *:0:0:1 ,ATTRS{idVendor}== 05e3 ,ATTRS{idProduct}== 0716 ,RUN+= /bin/umount -l /opt/usb_sd1_1 

但是在实际使用的时候,他们匹配不上,ACTION== remove ,KERNELS== *:0:0:1 与 ATTRS{idVendor}== 05e3 ,ATTRS{idProduct}== 0716 不能同时使用,如果直接改成:

ACTION== remove ,KERNELS== *:0:0:1 ,RUN+= /bin/umount -l /opt/usb_sd1_1 

命令功能可以实现,但是这样会出现于设备冲突的情况,在拔出该设备的时候,会把 KERNELS== *:0:0:1 的其他设备也卸载掉。

在这个时候,我们可以使用 devadm monitor –property   去监控设备拔出的时候它有哪些事件,有哪些属性可以被捕捉到并且与其他的设备属性不同以便区分不同的设备。下面是截取到的一部分数据:

[10:00:33]KERNEL[1555639338.737818] remove   /devices/platform/hiusb-ehci.0/usb1/1-2/1-2.3 (usb)
[10:00:33]UDEV_LOG=3
[10:00:33]ACTION=remove
[10:00:33]DEVPATH=/devices/platform/hiusb-ehci.0/usb1/1-2/1-2.3
[10:00:33]SUBSYSTEM=usb
[10:00:33]DEVNAME=bus/usb/001/007
[10:00:33]DEVTYPE=usb_device
[10:00:33]PRODUCT=5e3/716/9727
[10:00:33]TYPE=0/0/0
[10:00:33]BUSNUM=001
[10:00:33]DEVNUM=007
[10:00:33]SEQNUM=1024
[10:00:33]MAJOR=189
[10:00:33]MINOR=6

从上面可以看出,拔出的时候有个 PRODUCT,它是 idVendor 和 idProduct 值的一个组合,可以使用它来区分不同的设备。最终可以正常卸载设备的命令如下:

ACTION== remove ,SUBSYSTEM== usb ,ENV{PRODUCT}== 5e3/716/9727 ,RUN+= /bin/umount -l /opt/usb_sd1_1 

“linux6.5 udev 指的是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-12发表,共计9630字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)