转载于:https://linux.cn/article-9365-1.html

介绍

在 GNU/Linux 系统中,虽然设备的底层支持是在内核层面处理的,但是,它们相关的事件管理是在用户空间中通过 udev 来管理的。确切地说是由 udevd 守护进程来完成的。学习如何去写规则,并应用到发生的这些事件上,将有助于我们修改系统的行为并使它适合我们的需要。

规则如何组织

udev 规则是定义在一个以 .rules 为扩展名的文件中。那些文件主要放在两个位置:/usr/lib/udev/rules.d,这个目录用于存放系统安装的规则;/etc/udev/rules.d/ 这个目录是保留给自定义规则的。

定义那些规则的文件的命名惯例是使用一个数字作为前缀(比如,50-udev-default.rules),并且以它们在目录中的词汇顺序进行处理的。在 /etc/udev/rules.d 中安装的文件,会覆盖安装在系统默认路径中的同名文件。

规则语法

如果你理解了 udev 规则的行为逻辑,它的语法并不复杂。一个规则由两个主要的节构成:match 部分,它使用一系列用逗号分隔的键定义了规则应用的条件,而 action 部分,是当条件满足时,我们执行一些动作。

测试案例

讲解可能的选项的最好方法莫过于配置一个真实的案例,因此,我们去定义一个规则作为演示,当鼠标被连接时禁用触摸板。显然,在该规则定义中提供的属性将反映我的硬件。

我们将在 /etc/udev/rules.d/99-togglemouse.rules 文件中用我们喜欢的文本编辑器来写我们的规则。一条规则定义允许跨多个行,但是,如果是这种情况,必须在一个换行字符之前使用一个反斜线(\)表示行的延续,就和 shell 脚本一样。这是我们的规则:

  1. ACTION=="add" \
  2. , ATTRS{idProduct}=="c52f" \
  3. , ATTRS{idVendor}=="046d" \
  4. , ENV{DISPLAY}=":0" \
  5. , ENV{XAUTHORITY}="/run/user/1000/gdm/Xauthority" \
  6. , RUN+="/usr/bin/xinput --disable 16"

我们来分析一下这个规则。

操作符

首先,对已经使用以及将要使用的操作符解释如下:

== 和 != 操作符

== 是相等操作符,而 != 是不等于操作符。通过使用它们,我们可以确认规则上应用的键是否匹配各自的值。

分配操作符 = 和 :=

= 是赋值操作符,是用于为一个键赋值。当我们想要赋值,并且想确保它不会被其它规则所覆盖,我们就需要使用 := 操作符来代替,使用这个操作符分配的值,它就不能被改变。

+= 和 -= 操作符

+= 和 -= 操作符各自用于从一个指定的键定义的值列表中增加或者移除一个值。

我们使用的键

现在,来分析一下在这个规则中我们使用的键。首先,我们有一个 ACTION 键:通过使用它,当在一个设备上发生了特定的事件,我们将指定我们要应用的规则的具体内容。有效的值有 addremove  以及 change

然后,我们使用 ATTRS 关键字去指定一个属性去匹配。我们可以使用 udevadm info 命令去列出一个设备属性,提供它的名字或者 sysfs 路径即可:

  1. udevadm info -ap /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010/input/input39
  2. Udevadm info starts with the device specified by the devpath and then
  3. walks up the chain of parent devices. It prints for every device
  4. found, all possible attributes in the udev rules key format.
  5. A rule to match, can be composed by the attributes of the device
  6. and the attributes from one single parent device.
  7. looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010/input/input39':
  8. KERNEL=="input39"
  9. SUBSYSTEM=="input"
  10. DRIVER==""
  11. ATTR{name}=="Logitech USB Receiver"
  12. ATTR{phys}=="usb-0000:00:1d.0-1.2/input1"
  13. ATTR{properties}=="0"
  14. ATTR{uniq}==""
  15. looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1/0003:046D:C52F.0010':
  16. KERNELS=="0003:046D:C52F.0010"
  17. SUBSYSTEMS=="hid"
  18. DRIVERS=="hid-generic"
  19. ATTRS{country}=="00"
  20. looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.1':
  21. KERNELS=="2-1.2:1.1"
  22. SUBSYSTEMS=="usb"
  23. DRIVERS=="usbhid"
  24. ATTRS{authorized}=="1"
  25. ATTRS{bAlternateSetting}==" 0"
  26. ATTRS{bInterfaceClass}=="03"
  27. ATTRS{bInterfaceNumber}=="01"
  28. ATTRS{bInterfaceProtocol}=="00"
  29. ATTRS{bInterfaceSubClass}=="00"
  30. ATTRS{bNumEndpoints}=="01"
  31. ATTRS{supports_autosuspend}=="1"
  32. looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2':
  33. KERNELS=="2-1.2"
  34. SUBSYSTEMS=="usb"
  35. DRIVERS=="usb"
  36. ATTRS{authorized}=="1"
  37. ATTRS{avoid_reset_quirk}=="0"
  38. ATTRS{bConfigurationValue}=="1"
  39. ATTRS{bDeviceClass}=="00"
  40. ATTRS{bDeviceProtocol}=="00"
  41. ATTRS{bDeviceSubClass}=="00"
  42. ATTRS{bMaxPacketSize0}=="8"
  43. ATTRS{bMaxPower}=="98mA"
  44. ATTRS{bNumConfigurations}=="1"
  45. ATTRS{bNumInterfaces}==" 2"
  46. ATTRS{bcdDevice}=="3000"
  47. ATTRS{bmAttributes}=="a0"
  48. ATTRS{busnum}=="2"
  49. ATTRS{configuration}=="RQR30.00_B0009"
  50. ATTRS{devnum}=="12"
  51. ATTRS{devpath}=="1.2"
  52. ATTRS{idProduct}=="c52f"
  53. ATTRS{idVendor}=="046d"
  54. ATTRS{ltm_capable}=="no"
  55. ATTRS{manufacturer}=="Logitech"
  56. ATTRS{maxchild}=="0"
  57. ATTRS{product}=="USB Receiver"
  58. ATTRS{quirks}=="0x0"
  59. ATTRS{removable}=="removable"
  60. ATTRS{speed}=="12"
  61. ATTRS{urbnum}=="1401"
  62. ATTRS{version}==" 2.00"
  63. [...]

上面截取了运行这个命令之后的输出的一部分。正如你从它的输出中看到的那样,udevadm 从我们提供的指定路径开始,并且提供了所有父级设备的信息。注意设备的属性都是以单数的形式报告的(比如,KERNEL),而它的父级是以复数形式出现的(比如,KERNELS)。父级信息可以做为规则的一部分,但是同一时间只能有一个父级可以被引用:不同父级设备的属性混合在一起是不能工作的。在上面我们定义的规则中,我们使用了一个父级设备属性:idProduct 和 idVendor

在我们的规则中接下来做的事情是,去使用 ENV 关键字:它既可以用于设置也可以用于去匹配环境变量。我们给 DISPLAY 和 XAUTHORITY 分配值。当我们使用 X 服务器程序进行交互去设置一些需要的信息时,这些变量是非常必要的:使用 DISPLAY 变量,我们指定服务器运行在哪个机器上,用的是哪个显示和屏幕;使用 XAUTHORITY 提供了一个文件路径,其包含了 Xorg 认证和授权信息。这个文件一般位于用户的家目录中。

最后,我们使用了 RUN 字:它用于运行外部程序。非常重要:这里没有立即运行,但是一旦所有的规则被解析,将运行各种动作。在这个案例中,我们使用 xinput 实用程序去改变触摸板的状态。我不想解释这里的 xinput 的语法,它超出了本文的范围,只需要注意这个触摸板的 ID 是 16

规则设置完成之后,我们可以通过使用 udevadm test 命令去调试它。这个命令对调试非常有用,它并不真实去运行 RUN 指定的命令:

  1. $ udevadm test --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 路径的模拟动作。如果没有报告错误,说明我们的规则运行的很好。要在真实的环境中去使用它,我们需要重新加载规则:

  1. # udevadm control --reload

这个命令将重新加载规则文件,但是,它只对重新加载之后发生的事件有效果。

我们通过创建一个 udev 规则了解了基本的概念和逻辑,这只是 udev 规则中众多的选项和可能的设置中的一小部分。udev 手册页提供了一个详尽的列表,如果你想深入了解,请参考它。

udev的规则文件的更多相关文章

  1. 在Linux 5/6上使用UDEV SCSI规则配置ASM DISK

    格式化磁盘(略) 识别磁盘(/sbin/scsi_id)  Oracle Linux 5用如下脚本: #!/bin/sh for i in b c d e f g do echo "KERN ...

  2. 使用UDEV SCSI规则在Oracle Linux上配置ASM

    对于使用ASM管理的磁盘来说,需要一种能够用于一致性标识磁盘设备及其正确的所属关系和权限的手段.在Linux系统中,可以使用ASMLib来执行这项任务,但是这样做的缺点是在操作系统上增加了额外的一层, ...

  3. Struts2的输入校验(1)——校验规则文件的编写

    Struts2的输入校验(1) --校验规则文件的编写 Struts2提供了基于验证框架的输入校验,所有的输入校验只要编写配置文件,Struts2的验证框架将会负责进行服务器校验和客户端校验. 注: ...

  4. 如何在jenkins的maven项目中,用mvn命令行指定findbugs的黑名单规则文件

    一:问题背景 最近在研究jenkins的过程中,针对maven项目,打算添加findbugs进行静态检查,但我不太想在项目的pom中进行修改,最好可以只修改jenkins的job配置,即配置外部化. ...

  5. 抽取非基本验证到规则文件 - A2D规则引擎

    基本验证与业务验证,基本验证就是始终保持不变的验证规则,可以通过如下硬编码实现: public class Order { [Required] [Range(")] public deci ...

  6. 【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.1 规则文件

    转载至:https://blog.csdn.net/wo541075754/article/details/75150267 一个标准的规则文件的格式为已“.drl”结尾的文本文件,因此可以通过记事本 ...

  7. AWVS11提取规则文件

    在这里给大家分享一个获取AWVS规则文件的思路.  目前我提取的是17年4月份的扫描规则.   后面如果规则更新,可以自行提取 官网:   https://www.acunetix.com/vulne ...

  8. 《Drools7.0.0.Final规则引擎教程》第4章 4.1 规则文件

    一个标准的规则文件的格式为已".drl"结尾的文本文件,因此可以通过记事本工具进行编辑.规则放置于规则文件当中,一个规则文件可以放置多条规则.在规则文件当中也可以存放用户自定义的函 ...

  9. Drools学习笔记1—规则文件

    Facts(即普通的POJO) 指普通业务对象插入到Workingmemory后的对象规则可以对fact对象进行任意的对象操作是规则与应用系统交换的桥梁返回FactHandler对象,是插入到Work ...

随机推荐

  1. Validate US Telephone Numbers FreeCodeCamp

    function telephoneCheck(str) { // 祝你好运 //var re = /^1? ?(\(\d{3}\)|\d{3})[ |-]?\d{3}[ |-]?\d{4}$/; / ...

  2. 流量监控---iftop

    一.iftop是什么? iftop是类似于top的实时流量监控工具. 官方网站:http://www.ex-parrot.com/~pdw/iftop/ 二.iftop有什么用? iftop可以用来监 ...

  3. Python的基础知识01 _个人笔记

    1.快捷键:Alt+n 回到上一条语句>把上一条语句复制 Alt+p  去到下一条语句 2.Python 中不用“:”来表示一个语句 3.print("I Love you" ...

  4. Ubuntu 终端配置

    安装zsh apt install zsh 设置zsh为默认shell chsh -s /bin/zsh 恢复 bash 使用 chsh -s /bin/bash 安装 Oh My Zsh sh -c ...

  5. C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

  6. 移动端使用rem时候动态设置html字体大小

      !(function(doc, win) { var docEle = doc.documentElement, evt = "onorientationchange" in ...

  7. ORM框架 SQLAlchemy

    什么是ORM 使用关系对象映射进行数据库操作. 将对象转换成SQL,然后使用数据API执行SQL并获取执行结果. 分类 -DB first 手动创建数据库和表,自动生成类 -code first 手动 ...

  8. SpringMVC在对应绑定不同实体,但具有相同属性名的解决方案....

    在springmvc中,可以对前台传递过来的参数进行与后台实体绑定(第二种方式相对较好). 比如: 前台页面: <form action="${pageContext.request. ...

  9. php strtotime 同样的函数为何在不同的地方输出的结果不同?

    方法1:调用函数 date_default_timezone_set('Asia/Shanghai'); // 如果是中国的话 方法2:设置php.ini 中data.timezone [Date] ...

  10. Oracle的JDBC Url的几种方式

    1.普通SID方式jdbc:oracle:thin:username/password@x.x.x.1:1521:SID2.普通ServerName方式 jdbc:Oracle:thin:userna ...