什么是udev
udev(User space Daemon for device events,用户空间设备守护进程)是 Linux 系统中用于管理设备文件的工具,它在 Linux 内核和用户空间之间起到桥梁的作用。
udev是做什么的
- 动态管理设备文件
udev 能够根据内核提供的设备信息动态地创建、删除和管理这些设备文件。
例如,当用户插入一个 USB 存储设备时,内核会检测到这个硬件的变化,并通知 udev。udev 会根据预先定义的规则,为这个 USB 存储设备创建一个对应的设备文件,如 /dev/sdb 等。
- 设备规则的定制
udev 允许系统管理员通过编写规则文件来定制设备的管理方式。这些规则文件通常位于 /etc/udev/rules.d/ 目录下。规则文件中可以定义各种属性,如设备的名称、权限、符号链接等。
例如,如果用户希望将某个特定的 USB 设备挂载到一个固定的挂载点,可以通过在规则文件中指定设备的属性(如设备的序列号、厂商 ID 等)来实现。当这个 USB 设备被插入时,udev 会根据规则将其挂载到指定的目录。
- 触发设备事件
udev 能够触发各种设备事件,这些事件可以被其他应用程序捕获和处理。例如,当一个设备被插入或拔出时,udev 会发送一个事件通知,应用程序可以根据这些事件来执行相应的操作。
一个常见的例子是桌面环境中的设备管理器。当用户插入一个 USB 音频设备时,udev 会触发一个事件,设备管理器捕获到这个事件后,会自动弹出一个提示框,询问用户是否要播放音乐等操作。
udev 工作原理概述
- 内核通知
内核在检测到设备的添加或移除事件时,会通过 netlink 套接字向 udev 发送一个通知消息。这个消息包含了设备的相关信息,如设备的类型、路径、属性等。
- 规则匹配
udev 接收到通知后,会根据 /etc/udev/rules.d/ 目录下的规则文件来匹配设备。规则文件中定义了一系列的匹配条件,如设备的属性、环境变量等。udev 会逐一检查这些条件,找到与当前设备匹配的规则。
- 设备操作
当找到匹配的规则后,udev 会根据规则中定义的操作来处理设备。这些操作可能包括创建或删除设备文件、设置设备文件的权限和所有者、生成符号链接等。
例如,如果规则中指定要为设备创建一个符号链接 /dev/my_device,udev 就会在 /dev 目录下创建一个指向实际设备文件的符号链接。
udev如何触发后台任务
- 分析udev的具体规则
查看官方说法(udev),寻觅到 RUN 参数的阐释,能够目睹如下的描述内容,表明 udev 仅能运行能够迅速执行的命令,耗时长久的命令将会在 udev 事件终结之际被终止。
如果必须运行一个耗时长的命令,需要添加service服务来解决。
- 临时service服务
systemd-run 是一个非常强大的工具,用于在 systemd 环境中运行命令或程序,并将其作为临时服务(Transient Service)或持久服务(Persistent Service)启动。它允许用户动态地创建服务单元,而无需手动编写 .service 文件。
所以我们可以用systemd-run来实现后台任务执行。又因为我们需要命令不要阻塞,固需要添加--no-block参数
RUN+="/usr/bin/systemd-run --no-block <cmd>
但这种方式并不是通用性的,因为systemd只有在高版本下才有--no-block参数,固如果需要更通用的处理方式,需要编写service服务。
- 编写service服务
(1)调用的命令无参数
- 在/usr/lib/systemd/system/目录下,编写test.service服务
[Unit]
Description=Test Service
[Service]
ExecStart=/usr/bin/my_program
[Install]
WantedBy=multi-user.target
2. systemctl daemon-reload 3. 在/usr/lib/udev/rules.d/xxx-xxxx.rules下,添加触发条件
RUN+="/usr/bin/systemctl start --no-block test.service
(2)调用的命令有参数
- 在/usr/lib/systemd/system/目录下,编写<test@.service>服务
[Unit]
Description=Test Service
[Service]
ExecStart=/usr/bin/my_program %i
[Install]
WantedBy=multi-user.target
2. systemctl daemon-reload 3. 在/usr/lib/udev/rules.d/xxx-xxxx.rules下,添加触发条件
RUN+="/usr/bin/systemctl start --no-block test@args.service
结论
高版本,可以直接使用systemd-run --no-block直接调用命令,来实现命令的后台执行
通用策略,可以编写systemd的service配置服务,来实现命令的后台执行