读者应该了解udev背后的基本概念,并学习如何编写简单的规则。需要root权限中等难度约定#-要求给定的命令以root权限直接作为root用户或使用sudo命令运行。$-要求给定的命令以普通的非特权用户身份运行。简介在GNU/Linux系统中,虽然设备的底层支持是在内核级别处理的,但是它们相关的事件管理是通过udev在用户空间进行管理的。正是udevd守护进程所做的。学习如何编写规则并将其应用于这些事件将帮助我们修改系统的行为并使其适合我们的需要。规则是如何组织的udev规则是在扩展名为.rules的文件中定义的。那些文件主要放在两个位置:/usr/lib/udev/rules.d,这个目录用来存放系统安装的规则;/etc/udev/rules.d/这个目录是为自定义规则保留的。定义这些规则的文件的命名约定以数字为前缀(例如,50-udev-default.rules),并按照它们在目录中的词法顺序进行处理。安装在/etc/udev/rules.d中的文件会覆盖安装在系统默认路径中的同名文件。规则语法如果你了解udev规则的行为逻辑,它的语法并不复杂。规则由两个主要部分组成:匹配部分,它使用一系列以逗号分隔的键定义规则应用的条件,以及操作部分,当条件满足时我们执行一些操作。测试用例说明可能选项的最佳方式是配置真实用例,因此让我们定义一个规则作为演示,以在连接鼠标时禁用触摸板。显然,此规则定义中提供的属性将反映我的硬件。我们将在/etc/udev/rules.d/99-togglemouse.rules文件中用我们最喜欢的文本编辑器编写我们的规则。允许规则定义跨越多行,但如果是这种情况,换行符前面必须有反斜杠(\)以指示行继续,就像在shell脚本中一样。这是我们的规则:ACTION=="add"\,ATTRS{idProduct}=="c52f"\,ATTRS{idVendor}=="046d"\,ENV{DISPLAY}=":0"\,ENV{XAUTHORITY}="/run/user/1000/gdm/Xauthority"\,RUN+="/usr/bin/xinput--disable16"我们来分析一下这个规则。运算符首先对已经使用和将要使用的运算符进行说明:==和!=运算符==是等号运算符,!=是不等号运算符。通过使用它们,我们可以确认应用于规则的键与相应的值相匹配。赋值运算符=和:==是赋值运算符,用于将值分配给键。当我们想要分配一个值并希望确保它不被其他规则覆盖时,我们需要使用:=运算符来代替,并且不能更改使用该运算符分配的值。+=和-=运算符+=和-=运算符分别用于从指定键定义的值列表中添加或删除值。我们使用的键现在,让我们分析一下我们在这个规则中使用的键。首先,我们有一个ACTION键:通过使用它,我们将指定在设备上发生特定事件时要应用的规则的具体内容。有效值为添加、删除和更改。然后,我们使用ATTRS关键字指定要匹配的属性。我们可以使用udevadminfo命令列出设备属性,只需提供其名称或sysfs路径:udevadminfo-ap/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010/input/input39Udevadm信息从devpath指定的设备开始,然后沿着父设备链向上移动。它为找到的每个设备打印udev规则密钥格式中的所有可能属性。要匹配的规则可以由设备的属性和来自单个父设备的属性组成。查看设备'/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010/input/input39':KERNEL=="input39"SUBSYSTEM=="input"DRIVER=""ATTR{name}=="LogitechUSBReceiver"ATTR{phys}=="usb-0000:00:1d.0-1.2/input1"ATTR{properties}=="0"ATTR{uniq}==""查看父设备'/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010':内核==“0003:046D:C52F.0010"SUBSYSTEMS=="hid"DRIVERS=="hid-generic"ATTRS{country}=="00"查看父设备'/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1':KERNELS=="2-1.2:1.1"SUBSYSTEMS=="usb"DRIVERS=="usbhid"ATTRS{authorized}=="1"ATTRS{bAlternateSetting}==“0”ATTRS{bInterfaceClass}==“03”ATTRS{bInterfaceNumber}==“01”ATTRS{bInterfaceProtocol}==“00”ATTRS{bInterfaceSubClass}==“00”ATTRS{bNumEndpoints}==“01”ATTRS{supports_autosuspend}=="1"查看父设备'/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2':KERNELS=="2-1.2“SUBSYSTEMS==”usb”DRIVERS==”usb”ATTRS{authorized}==”1”ATTRS{avoid_reset_quirk}==”0”ATTRS{bConfigurationValue}==”1”ATTRS{bDeviceClass}==“00”ATTRS{bDeviceProtocol}==“00”ATTRS{bDeviceSubClass}==“00”ATTRS{bMaxPacketSize0}==“8”ATTRS{bMaxPower}==“98mA”ATTRS{bNumConfigurations}==”1"ATTRS{bNumInterfaces}=="2"ATTRS{bcdDevice}=="3000"ATTRS{bmAttributes}=="a0"ATTRS{busnum}=="2"ATTRS{configuration}=="RQR30.00_B0009"ATTRS{devnum}==“12”ATTRS{devpath}==“1.2”ATTRS{idProduct}==“c52f”ATTRS{idVendor}==“046d”ATTRS{ltm_capable}==“无”ATTRS{制造商}==“罗技”ATTRS{maxchild}==“0”ATTRS{product}==“USB接收器”ATTRS{quirks}==“0x0”ATTRS{removable}==“removable”ATTRS{speed}==“12”ATTRS{urbnum}=="1401"ATTRS{version}=="2.00"[...]以上是运行此命令后的部分输出从它的输出可以看出,udevadm从我们提供的指定路径开始,并提供有关所有父设备的信息。请注意,设备的属性以单数形式报告(例如,KERNEL),而其父设备以复数形式报告(例如,KERNELS)。父母信息可以是规则的一部分,但一次只能引用一个父母:不同父母设备的混合属性将不起作用。在我们上面定义的规则中,我们使用了父设备属性:idProduct和idVendor。在我们的规则中接下来要做的是使用ENV关键字:它可以用于设置和匹配环境变量。我们给DISPLAY和XAUTHORITY赋值。当我们使用X服务器程序交互设置一些需要的信息时,这些变量是非常必要的:使用DISPLAY变量,我们指定服务器运行在哪台机器上,使用什么显示器和屏幕;使用XAUTHORITY提供一个文件路径,其中包含Xorg身份验证和授权信息。该文件通常位于用户的主目录中。***,我们用了RUN这个词:它是用来运行一个外部程序的。非常重要:这不会立即运行,但会在解析完所有规则后运行各种操作。在这种情况下,我们使用xinput实用程序来更改触摸板的状态。这里不想解释xinput的语法,这超出了本文的范围,只需要注意这个touchpad的ID是16即可。设置规则后,我们可以使用udevadmtest命令进行调试。这个命令对于调试非常有用,它实际上并不运行RUN指定的命令:$udevadmtest--action="add"/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010/input/input39我们向命令提供的是使用--action选项和设备的sysfs路径的模拟操作。如果没有错误报告,我们的规则工作正常。要在真实环境中使用它,我们需要重新加载规则:#udevadmcontrol--reload此命令将重新加载规则文件,但是,它只对重新加载后发生的事件有影响。我们通过创建udev规则了解了基本概念和逻辑,这只是udev规则中许多选项和可能设置的一小部分。udev手册页提供了详尽的列表,如果您想更深入地了解,请参考它。
