本文主要是介绍linux :udev规则详细介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
udev规则介绍
by Daniel Drake (dsd)
翻译:嵌入式学吒(GLL)
目录
udev规则介绍
介绍
概念
为什么?
写规则
规则文件和语义
语法规则
基本规则
匹配sysfs属性
设备层次结构
字符串替换
字符串匹配
从sysfs中查找信息
sysfs树
udevinfo
替代方法
高级的主题
控制权限和所有权
使用外部程序来命名设备
在某些事件上运行外部程序
环境相互作用
附加选项
举例
1.USB打印机
2.USB摄像头
3.USB读卡器
4.USB掌上电脑
5.CD / DVD驱动器:
6.网络接口
测试和调试
将你的规则付诸行动
udevtest
介绍
关于本文档
udev的目标是Linux内核2.6以及更高版本,为动态/dev目录提供用户空间解决方案,并使用持久的设备命名。以前的/dev实现devfs现在被弃用,udev被视为它的继任者。udev与devfs是一个敏感的话题——在进行比较之前,您应该阅读本文。
多年来,您可能使用udev规则的内容发生了变化,规则本身的灵活性也发生了变化。在现代系统中,udev为某些设备类型提供了开箱即用的持久性命名,从而消除了对这些设备的自定义规则的需要。然而,一些用户仍然需要额外的定制级别。
本文档假设您已经安装了udev并使用默认配置运行正常。这通常由您的Linux发行版来处理。
本文档并没有涵盖规则编写的每个细节,但是它的目的是介绍所有的主要概念。更详细的细节可以在udev手册页中找到。
概念
术语:devfs、sysfs、节点等。
一个基本的介绍,可能不完全准确。
在典型的基于linux的系统上,/dev目录用于存储类似文件的设备节点,这些节点指向系统中的某些设备。每个节点都指向系统(设备)的一部分,该部分可能存在,也可能不存在。用户空间应用程序可以使用这些设备节点与系统硬件进行交互,例如,X服务器将“侦听”/dev/input/mice,以便将用户的鼠标移动与移动可视鼠标指针联系起来。
最初的/dev目录只是用可能出现在系统中的每个设备填充。由于这个原因,/dev目录通常非常大。devfs提供了一种更易于管理的方法(值得注意的是,它只使用插入系统的硬件来填充/dev),以及一些其他功能,但是系统被证明存在一些难以修复的问题。
udev是管理/dev目录的“新”方法,旨在清除以前/dev实现中的一些问题,并提供一个健壮的前进路径。为了创建和命名与系统中存在的设备相对应的/dev设备节点,udev依赖于sysfs提供的信息与用户提供的规则进行匹配。本文档旨在详细描述规则编写的过程,这是用户必须(可选地)执行的惟一与udv相关的任务之一。
sysfs是2.6内核的一个新文件系统。它由内核管理,并导出当前插入系统的设备的基本信息。udev可以使用这些信息来创建与您的硬件相对应的设备节点。sysfs安装在/sys上,可以浏览。在接触udev之前,您可能希望研究一下存储在那里的一些文件。在本文中,我将交替使用术语/sys和sysfs。
为什么?
udev规则非常灵活和强大。以下是一些你可以使用规则来实现的事情:
将设备节点从默认名称重命名为其他名称
通过创建到默认设备节点的符号链接,为设备节点提供一个可选/持久性名称
根据程序的输出来命名设备节点
更改设备节点的权限和所有权
在创建或删除设备节点时启动脚本(通常在连接或断开设备时)
重命名网络接口
对于不存在特定设备的设备节点的问题,编写规则不是一种变通方法。即使没有匹配的规则,udev也会用内核提供的默认名称创建设备节点。
持久地命名设备节点有几个优点。假设你有两个USB存储设备:一个数码相机和一个u盘。这些设备通常被分配给设备节点/dev/sda和/dev/sdb,但是确切的分配取决于它们最初连接的顺序。这可能会给一些用户带来问题,如果每个设备每次都能被持久地命名,比如/dev/camera和/dev/flashdisk,这些用户将受益匪浅
内置的持久性命名方案
udev为一些设备类型提供了开箱即用的持久性命名。这是一个非常有用的特性,在很多情况下意味着您的旅程到此结束:您不必编写任何规则。
udev为/dev/disk目录中的存储设备提供开箱即用的持久性命名。要查看为存储硬件创建的持久性名称,可以使用以下命令:
# ls -lR /dev/disk
这适用于所有存储类型。例如,udev创建了/dev/disk/by-id/scsi-SATA_ST3120827AS_4MS1NDXZ-part3,它是到我的根分区的一个持久命名的符号链接。udev创建/dev/disk/by-id/usb-Prolific_Technology_Inc。_USB_Mass_Storage_Device-part1当我插入我的u盘时,它也是一个持久性名称。
写规则
规则文件和语义
在决定如何命名设备以及执行哪些附加操作时,udev会读取一系列规则文件。这些文件保存在/etc/ udv /rules中它们都必须有.rules后缀。
默认的udev规则存储在/etc/udev/rules.d/50-udev.rules中。您可能会发现查看这个文件很有趣——它包括一些示例,然后是一些证明devfs样式/dev布局的默认规则。但是,不应该将规则直接写入这个文件。
文件/etc/udev/rules.d/按词法顺序解析,在某些情况下,解析规则的顺序很重要。通常,您希望在缺省值之前解析您自己的规则,因此我建议您在/etc/udev/rules.d/10-local.rules上创建一个文件,并将所有规则写入该文件。
在规则文件中,以“#”开头的行被视为注释。每隔一个非空行就是一个规则。规则不能跨多行。
一个设备可以由多个规则匹配。这有它的实际优势,例如,我们可以编写两个匹配相同设备的规则,其中每个规则为设备提供自己的备用名称。即使规则在不同的文件中,也会创建两个替代名称。重要的是要理解udev在发现匹配规则时不会停止处理,它将继续搜索并尝试应用它所知道的每个规则。
语法规则
每个规则都由一系列键-值对构成,这些键-值对由逗号分隔。匹配键是用来识别规则所作用的设备的条件。当规则中的所有匹配键都对应于正在处理的设备时,将应用该规则并调用赋值键的操作。每个规则应该由至少一个匹配键和至少一个赋值键组成。
下面是一个例子规则来说明上述情况:
KERNEL=="hdb", NAME="my_spare_disk"
上面的规则包括一个匹配键(内核)和一个赋值键(名称)。这些键及其属性的语义将在后面详细介绍。需要注意的是,match键通过相等运算符(==)与它的值相关,而赋值键通过赋值运算符(=)与它的值相关。
注意udev不支持任何形式的行延续。不要在您的规则中插入任何换行符,因为这将导致udev将您的一个规则视为多个规则,并且不能按预期工作。
基本规则
udev提供了几个不同的匹配键,可以用来编写非常精确地匹配设备的规则。下面介绍一些最常用的键,其他的将在本文档的后面介绍。有关完整列表,请参见udev手册页。
内核-匹配设备的内核名称
子系统-与设备的子系统匹配
驱动程序-匹配支持设备的驱动程序的名称
在您使用了一系列匹配键来精确匹配设备之后,udev通过一系列赋值键为您提供了对接下来发生的事情的精细控制。有关可能的赋值键的完整列表,请参见udev手册页。下面介绍最基本的赋值键。其他内容将在本文档后面介绍。
NAME—设备节点的应使用名称
符号链接——作为设备节点替代名称的符号链接列表
如上所述,udev只为一个设备创建一个真正的设备节点。如果希望为该设备节点提供替代名称,可以使用符号链接功能。使用符号链接分配,您实际上维护了一个符号链接列表,所有这些链接都指向实际的设备节点。为了操作这些链接,我们引入了一个新的操作符,用于向列表添加内容:+=。通过用空格分隔每个符号链接,可以将多个符号链接从任何一个规则附加到列表。
KERNEL=="hdb", NAME="my_spare_disk"
上面的规则是:匹配一个被内核命名为hdb的设备,将设备节点命名为my_spare_disk而不是hdb。设备节点出现在/dev/my_spare_disk。
KERNEL=="hdb", DRIVER=="ide-disk", SYMLINK+="sparedisk"
上面的规则是:匹配一个被内核命名为hdb的设备,并且驱动程序是ide-disk。将设备节点命名为默认名称,并创建一个名为sparedisk的符号链接。注意,我们没有指定设备节点名,所以udev使用缺省值。为了保持标准/dev布局,您自己的规则通常会保留名称,但创建一些符号链接和/或执行其他分配。
KERNEL=="hdc", SYMLINK+="cdrom cdrom0"
上面的规则可能是您正在编写的规则类型中比较典型的。它在/dev/cdrom和/dev/cdrom0上创建两个符号链接,它们都指向/dev/hdc同样,没有指定名称分配,因此使用默认的内核名称(hdc)。
匹配sysfs属性
到目前为止,引入的匹配键只提供有限的匹配功能。实际上,我们需要更精细的控制:我们希望根据高级属性(如供应商代码、确切的产品编号、序列号、存储容量、分区数量等)来识别设备。
许多驱动程序将这样的信息导出到sysfs中,udev允许我们将sysfs匹配合并到规则中,使用ATTR键,语法略有不同。
下面是一个示例规则,它匹配来自sysfs的单个属性。本文档后面将提供进一步的详细信息,这些信息将帮助您编写基于sysfs属性的规则。
SUBSYSTEM=="block", ATTR{size}=="234441648", SYMLINK+="my_disk"
设备层次结构
Linux内核实际上以树状结构表示设备,这些信息通过sysfs公开,在编写规则时非常有用。例如,我的硬盘设备的设备表示是SCSI磁盘设备的一个子设备,而SCSI磁盘设备又是串行ATA控制器设备的一个子设备,串行ATA控制器设备又是PCI总线设备的一个子设备。您可能会发现自己需要引用有关设备的父设备的信息,例如我的硬盘设备的序列号在设备级别上没有公开,而是由它的直接父设备在SCSI磁盘级别上公开。
到目前为止介绍的四个主要匹配键(内核/子系统/驱动程序/ATTR)只匹配与相关设备对应的值,而不匹配来自父设备的值。udev提供了匹配键的变体,可以在树中向上搜索:
KERNELS——匹配设备的内核名,或者任何父设备的内核名
子系统-匹配设备的子系统,或任何父设备的子系统
驱动程序-匹配支持设备的驱动程序的名称,或支持任何父设备的驱动程序的名称
ATTRS—匹配设备的sysfs属性,或任何父设备的sysfs属性
考虑到层次结构,您可能会觉得编写规则变得有点复杂。请放心,这里有一些工具可以提供帮助,稍后将介绍这些工具。
字符串替换
在编写可能处理多个类似设备的规则时,udev类似printf的字符串替换操作符非常有用。您可以简单地将这些操作符包含在规则所做的任何赋值中,udev将在执行它们时对它们求值。
最常见的操作符是%k和%n。%k计算为设备的内核名,例如。“sda3”表示设备(默认情况下)出现在/dev/sda3%n的计算结果为设备的内核号(存储设备的分区号),例如。/dev/sda3.“3”
udev还为更高级的功能提供了其他几个替代操作符。阅读完本文其余部分后,请查阅udev手册页。对于这些操作符还有另一种可选的语法——上面示例中的$kernel和$number。因此,如果希望在规则中匹配文字%,则必须编写%%,如果希望匹配文字$,则必须编写$$。
为了说明字符串替换的概念,下面给出了一些示例规则。
KERNEL=="mice", NAME="input/%k"
KERNEL=="loop0", NAME="loop/%n", SYMLINK+="%k"
第一个规则确保mice设备节点只出现在/dev/input目录中(默认情况下是/dev/mice)。第二条规则确保在/dev/loop/0处创建名为loop0的设备节点,但也像往常一样在/dev/loop0处创建一个符号链接。
上述规则的使用值得怀疑,因为它们都可以在不使用任何替换操作符的情况下重写。这些替换的真正威力将在下一节中变得更加明显。
字符串匹配
与精确匹配字符串一样,udev允许您使用shell样式的模式匹配。支持3种模式:
* -匹配任何字符,0次或更多次
?-匹配任何字符一次
[] -匹配方括号中指定的任何单个字符,也允许使用范围
下面是一些包含上述模式的示例。注意字符串替换操作符的使用。
KERNEL=="fd[0-9]*", NAME="floppy/%n", SYMLINK+="%k"
KERNEL=="hiddev*", NAME="usb/%k"
第一个规则匹配所有软盘驱动器,确保设备节点位于/dev/floppy目录中,并根据默认名称创建一个符号链接。第二条规则确保hiddev设备只出现在/dev/usb目录中。
从sysfs中查找信息
sysfs树
使用来自sysfs的有趣信息的概念在上面简单地提到过。为了编写基于此信息的规则,首先需要知道属性的名称及其当前值。
sysfs实际上是一个非常简单的结构。它在逻辑上被划分为目录。每个目录包含许多文件(属性),这些文件(属性)通常只包含一个值。存在一些符号链接,它们将设备链接到它们的父设备。上面已经提到了层次结构。
有些目录被称为顶级设备路径。这些目录表示具有相应设备节点的实际设备。顶级设备路径可以归类为包含一个dev文件的sysfs目录,下面的命令将为您列出这些:
# find /sys -name dev
例如,在我的系统中,/sys/block/sda目录是硬盘的设备路径。它通过/sys/block/sda/device符号链接链接到它的父设备SCSI磁盘设备。
当您编写基于sysfs信息的规则时,您只是在链的一部分中匹配某些文件的属性内容。例如,我可以读取我的硬盘大小如下:
# cat /sys/block/sda/size
234441648
在udev规则中,我可以使用ATTR{size}=="234441648"来标识这个磁盘。当udev遍历整个设备链时,我可以选择使用ATTRS来匹配链的另一部分的属性(例如/sys/class/block/sda/device/中的属性),但是在处理链的不同部分时会有一些注意事项,后面会介绍。
虽然这对于介绍sysfs的结构和udev如何匹配值是很有用的,但是手工遍历sysfs既费时又不必要。
udevinfo
输入udevinfo,它可能是您可以用来构造规则的最直接的工具。您需要知道的只是所涉及设备的sysfs设备路径。一个精简的例子如下:
# udevinfo -a -p /sys/block/sda
looking at device '/block/sda':
KERNEL=="sda"
SUBSYSTEM=="block"
ATTR{stat}==" 128535 2246 2788977 766188 73998 317300 3132216 5735004 0 516516 6503316"
ATTR{size}=="234441648"
ATTR{removable}=="0"
ATTR{range}=="16"
ATTR{dev}=="8:0"
looking at parent device '/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0':
KERNELS=="0:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{ioerr_cnt}=="0x0"
ATTRS{iodone_cnt}=="0x31737"
ATTRS{iorequest_cnt}=="0x31737"
ATTRS{iocounterbits}=="32"
ATTRS{timeout}=="30"
ATTRS{state}=="running"
ATTRS{rev}=="3.42"
ATTRS{model}=="ST3120827AS "
ATTRS{vendor}=="ATA "
ATTRS{scsi_level}=="6"
ATTRS{type}=="0"
ATTRS{queue_type}=="none"
ATTRS{queue_depth}=="1"
ATTRS{device_blocked}=="0"
looking at parent device '/devices/pci0000:00/0000:00:07.0':
KERNELS=="0000:00:07.0"
SUBSYSTEMS=="pci"
DRIVERS=="sata_nv"
ATTRS{vendor}=="0x10de"
ATTRS{device}=="0x037f"
正如您所看到的,udevinfo只是生成一个属性列表,您可以在udev规则中按原样使用这些属性作为匹配键。从上面的例子,我可以为这个设备产生以下两个规则之一:
SUBSYSTEM=="block", ATTR{size}=="234441648", NAME="my_hard_disk"SUBSYSTEM=="block", SUBSYSTEMS=="scsi", ATTRS{model}=="ST3120827AS", NAME="my_hard_disk"
你可能已经注意到在上面的例子中颜色的使用。这是为了证明,尽管将相关设备的属性与单个父设备的属性组合在一起是合法的,但是不能将多个父设备的属性混合并匹配——您的规则将不起作用。例如,下面的规则是无效的,因为它试图匹配来自两个父设备的属性:
SUBSYSTEM=="block", ATTRS{model}=="ST3120827AS", DRIVERS=="sata_nv", NAME="my_hard_disk"
通常会为您提供大量的属性,您必须从中选择一些来构建规则。通常,您希望选择以一种持久的、人类可识别的方式标识设备的属性。在上面的示例中,我选择了磁盘的大小及其型号。我没有使用毫无意义的数字,比如ATTRS{iodone_cnt}==“0x31737”。
观察udevinfo输出中层次结构的效果。问题设备对应的绿色部分使用标准匹配键,如KERNEL和ATTR。与父设备对应的蓝色和栗色部分使用父设备遍历变量,如子系统和ATTRS。这就是层次结构引入的复杂性实际上很容易处理的原因,只要确保使用udevinfo建议的确切值即可。
另一点需要注意的是,文本属性通常出现在udevinfo输出中,用空格填充(例如,请参见上面的ST3120827AS)。在您的规则中,您可以指定额外的空格,也可以像我这样将它们截断。
使用udevinfo的惟一复杂之处在于,您需要知道顶级设备路径(在上面的示例中是/sys/block/sda)。这并不总是显而易见的。但是,由于您通常要为已经存在的设备节点编写规则,所以可以使用udevinfo为您查找设备路径:
# udevinfo -a -p $(udevinfo -q path -n /dev/sda)
替代方法
尽管udevinfo几乎可以肯定是列出可以用来构建规则的确切属性的最直接的方法,但是有些用户更喜欢其他工具。usbview等实用程序显示类似的一组信息,其中大部分可以在规则中使用。
高级的主题
控制权限和所有权
udev允许您在规则中使用附加的赋值来控制每个设备上的所有权和权限属性。
组分配允许您定义哪个Unix组应该拥有设备节点。下面是一个示例规则,它定义了视频组将拥有framebuffer设备:
KERNEL=="fb[0-9]*", NAME="fb/%n", SYMLINK+="%k", GROUP="video"
所有者键(可能不太有用)允许您定义哪个Unix用户应该拥有设备节点上的所有者权限。假设您希望john拥有您的软盘设备,您可以使用:
KERNEL=="fd[0-9]*", OWNER="john"
udev默认创建Unix权限为0660的节点(对所有者和组的读/写)。如果需要,可以使用包括模式分配在内的规则在某些设备上覆盖这些默认设置。例如,下面的规则定义了inotify节点应该对每个人都是可读可写的:
KERNEL=="inotify", NAME="misc/%k", SYMLINK+="%k", MODE="0666"
使用外部程序来命名设备
在某些情况下,您可能需要比标准udev规则所能提供的更大的灵活性。在这种情况下,您可以要求udev运行一个程序,并使用该程序的标准输出来提供设备命名。
要使用此功能,只需在程序分配中指定要运行的程序的绝对路径(以及任何参数),然后在名称/符号链接分配中使用%c替换的某些变体。
下面的示例引用了在/bin/device_namer中找到的一个虚构程序。device_namer接受一个命令行参数,该参数是设备的内核名。基于这个内核名,device_namer执行它的操作,并向通常的标准输出管道生成一些输出,这些输出被分成几个部分。每个部分都是一个单词,每个部分由一个空格分隔。
在我们的第一个示例中,我们假设device_namer输出若干个部分,每个部分组成一个符号链接(可选名称),用于相关设备。
KERNEL=="hda", PROGRAM="/bin/device_namer %k", SYMLINK+="%c"
下一个示例假设device_namer输出两个部分,第一个部分是设备名,第二个部分是附加符号链接的名称。我们现在引入%c{N}替换,它指的是输出的第N部分:
KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2}"
下一个示例假设device_namer输出设备名称的一个部分,然后输出任意数量的组成额外符号链接的部分。我们现在引入%c{N+}替换,它的计算结果是第N部分,第N+1部分,第N+2部分,…直到输出结束。
KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2+}"
输出部分可以用于任何赋值键,而不仅仅是名称和符号链接。下面的示例使用一个虚构的程序来确定应该拥有该设备的Unix组:
KERNEL=="hda", PROGRAM="/bin/who_owns_device %k", GROUP="%c"
在某些事件上运行外部程序
编写udev规则的另一个原因是在设备连接或断开连接时运行特定的程序。例如,您可能希望执行一个脚本,以便在连接数码相机时自动从相机下载所有照片。
不要将此与上面描述的程序功能混淆。程序用于运行产生设备名称的程序(它们不应该做其他任何事情)。当这些程序被执行时,设备节点还没有被创建,因此以任何方式对设备进行操作都是不可能的。
这里介绍的功能允许您在设备节点就位后运行程序。这个程序可以作用于设备,但是它不能长时间运行,因为udev在这些程序运行时被有效地暂停。解决此限制的一种方法是确保程序立即分离自己。
下面是一个示例规则,演示了如何使用运行列表分配:
KERNEL=="sdb", RUN+="/usr/bin/my_program"
当执行/usr/bin/my_program时,udev环境的各个部分都可以作为环境变量使用,包括关键值,比如子系统。您还可以使用ACTION环境变量来检测设备是否正在连接或断开连接——ACTION将分别是“添加”或“删除”。
udev不会在任何活动终端上运行这些程序,也不会在shell的上下文中执行它们。确保您的程序被标记为可执行的,如果它是一个shell脚本,则确保它以适当的shebang(例如#!/bin/sh)开始,并且不要期望任何标准输出出现在您的终端上。
环境相互作用
udev为环境变量提供了一个ENV键,可用于匹配和赋值。
在赋值的情况下,您可以设置环境变量,稍后您可以对其进行匹配。您还可以设置环境变量,任何使用上述技术调用的外部程序都可以使用这些变量。下面显示了设置环境变量的虚构示例规则。
KERNEL=="fd0", SYMLINK+="floppy", ENV{some_var}="value"
在匹配的情况下,可以确保只根据环境变量的值运行规则。注意,udev看到的环境与您在控制台看到的用户环境不同。下面显示了一个涉及环境匹配的虚构规则。
KERNEL=="fd0", ENV{an_env_var}=="yes", SYMLINK+="floppy"
如果在udev的环境中将$an_env_var设置为“yes”,那么上面的规则只会创建/dev/floppy链接。
附加选项
另一个有用的任务是选项列表。有几个选择:
all_partitions—为一个块设备创建所有可能的分区,而不是只创建那些最初检测到的分区
ignore_device—完全忽略事件
last_rule—确保以后的规则没有任何作用
例如,下面的规则设置了我的硬盘节点上的组所有权,并确保以后的任何规则都不会有任何影响:
KERNEL=="sda", GROUP="disk", OPTIONS+="last_rule"
举例
1.USB打印机
我打开打印机,它被分配到设备节点/dev/lp0。不满足于这样一个平淡的名字,我决定使用udevinfo来帮助我编写一个规则,它将提供一个替代名称:
# udevinfo -a -p $(udevinfo -q path -n /dev/lp0)
looking at device '/class/usb/lp0':
KERNEL=="lp0"
SUBSYSTEM=="usb"
DRIVER==""
ATTR{dev}=="180:0"
looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb1/1-1':
SUBSYSTEMS=="usb"
ATTRS{manufacturer}=="EPSON"
ATTRS{product}=="USB Printer"
ATTRS{serial}=="L72010011070626380"
我的规则是:
SUBSYSTEM=="usb", ATTRS{serial}=="L72010011070626380", SYMLINK+="epson_680"
2.USB摄像头
与大多数相机一样,我的相机将自己标识为通过USB总线连接的外部硬盘,使用SCSI传输。为了访问我的照片,我安装了驱动器,并将图像文件复制到我的硬盘上。并不是所有的相机都是这样工作的:有些相机使用非存储协议,比如gphoto2支持的相机。在gphoto的情况下,您不希望为您的设备编写规则,因为它完全是通过用户空间(而不是特定的内核驱动程序)进行控制的。
USB照相设备的一个常见问题是,它们通常将自己标识为带有单个分区的磁盘,在本例中是/dev/sdb和/dev/sdb1sdb节点对我来说毫无用处,但是sdb1很有趣—这是我想挂载的节点。这里有一个问题,因为sysfs是链接的,所以udevinfo为/dev/sdb1生成的有用属性与/dev/sdb1相同。这将导致您的规则可能同时匹配原始磁盘和分区,这不是您想要的,您的规则应该是特定的。
# udevinfo -a -p $(udevinfo -q path -n /dev/sdb1)
looking at device '/block/sdb/sdb1':
KERNEL=="sdb1"
SUBSYSTEM=="block"
looking at parent device '/devices/pci0000:00/0000:00:02.1/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':
KERNELS=="6:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{rev}=="1.00"
ATTRS{model}=="X250,D560Z,C350Z"
ATTRS{vendor}=="OLYMPUS "
ATTRS{scsi_level}=="3"
ATTRS{type}=="0"
我的规则:
KERNEL=="sd?1", SUBSYSTEMS=="scsi", ATTRS{model}=="X250,D560Z,C350Z", SYMLINK+="camera"
USB硬盘
一个USB硬盘可以和我上面描述的USB相机相比,但是典型的使用模式是不同的。在相机的例子中,我解释说我对sdb节点不感兴趣——它只用于分区(例如使用fdisk),但我为什么要对相机分区!?
当然,如果你有一个100GB的USB硬盘,你想对它进行分区是完全可以理解的,在这种情况下,我们可以利用udev的字符串替换:
KERNEL=="sd*", SUBSYSTEMS=="scsi", ATTRS{model}=="USB 2.0 Storage Device", SYMLINK+="usbhd%n"
该规则创建符号链接,如:
/dev/usbhd - The fdiskable node
/dev/usbhd1 - The first partition (mountable)
/dev/usbhd2 - The second partition (mountable)
3.USB读卡器
USB读卡器(CompactFlash、SmartMedia等)是另一种用途不同的USB存储设备。
这些设备通常不会在媒体改变时通知主机。因此,如果您在没有介质的设备上插入数据,然后插入一张卡,计算机就不会意识到这一点,并且您没有用于介质的可挂载sdb1分区节点。
一个可能的解决方案是利用all_partitions选项,它将为规则匹配的每个块设备创建16个分区节点:
KERNEL="sd*", SUBSYSTEMS=="scsi", ATTRS{model}=="USB 2.0 CompactFlash Reader", SYMLINK+="cfrdr%n", OPTIONS+="all_partitions"
现在您将拥有以下节点:cfrdr、cfrdr1、cfrdr2、cfrdr3、…,cfrdr15。
4.USB掌上电脑
这些设备作为USB-serial设备工作,因此在默认情况下,您只能获得ttyUSB1设备节点。palm实用程序依赖于/dev/pilot,因此许多用户希望使用规则来提供此功能。
Carsten Clasohm的博客文章似乎是这个问题的权威来源。Carsten规则如下:
SUBSYSTEMS=="usb", ATTRS{product}=="Palm Handheld", KERNEL=="ttyUSB*", SYMLINK+="pilot"
注意,产品字符串似乎因产品而异,所以一定要检查(使用udevinfo)哪个字符串适用于您。
5.CD / DVD驱动器:
我这台电脑有两个光驱:一个DVD阅读器(hdc)和一个DVD改写器(hdd)。我不希望这些设备节点改变,除非我物理地重新连接我的系统。但是,为了方便,许多用户喜欢使用/dev/dvd这样的设备节点。
我们知道这些设备的内核名称,规则编写很简单。以下是我的系统的一些例子:
SUBSYSTEM=="block", KERNEL=="hdc", SYMLINK+="dvd", GROUP="cdrom"
SUBSYSTEM=="block", KERNEL=="hdd", SYMLINK+="dvdrw", GROUP="cdrom"
6.网络接口
即使通过名称引用它们,网络接口通常也没有与它们相关联的设备节点。尽管如此,规则编写过程几乎是相同的。
简单地匹配规则中接口的MAC地址是有意义的,因为这是惟一的。但是,请确保使用与udevinfo相同的MAC地址,因为如果不完全匹配,则规则将不起作用。
# udevinfo -a -p /sys/class/net/eth0
looking at class device '/sys/class/net/eth0':
KERNEL=="eth0"
ATTR{address}=="00:52:8b:d5:04:48"
这是我的原则:
KERNEL=="eth*", ATTR{address}=="00:52:8b:d5:04:48", NAME="lan"
测试和调试
将你的规则付诸行动
假设您使用的是支持inotify的最新内核,udev将自动监视您的规则目录,并自动获取您对规则文件所做的任何修改。
尽管如此,udev不会自动重新处理所有设备并尝试应用新规则。例如,如果您编写了一个规则,以便在您的相机插入时为其添加一个额外的符号链接,那么您不能期望这个额外的符号链接立即出现。
要使符号链接显示出来,您可以断开并重新连接您的相机,或者在不可移动设备的情况下,您可以运行udevtrigger。
如果您的内核不支持inotify,则不会自动检测到新规则。在这种情况下,您必须在对规则文件进行任何修改之后运行udevcontrol reload_rules,以便这些修改生效。
udevtest
如果您知道sysfs中的顶级设备路径,您可以使用udevtest来显示udev将采取的操作。这可以帮助您调试规则。例如,假设你想调试一个作用于/sys/class/sound/dsp的规则:
# udevtest /class/sound/dsp
main: looking at device '/class/sound/dsp' from subsystem 'sound'
udev_rules_get_name: add symlink 'dsp'
udev_rules_get_name: rule applied, 'dsp' becomes 'sound/dsp'
udev_device_event: device '/class/sound/dsp' already known, remove possible symlinks
udev_node_add: creating device node '/dev/sound/dsp', major = '14', minor = '3', mode = '0660', uid = '0', gid = '18'
udev_node_add: creating symlink '/dev/dsp' to 'sound/dsp'
注意,/sys前缀已从udevtest命令行参数中删除,这是因为udevtest操作设备路径。还要注意的是,udevtest纯粹是一个测试/调试工具,它不创建任何设备节点,不管输出是什么!
这篇关于linux :udev规则详细介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!