udev加载驱动
信息传递的核心链路
内核设备驱动检测到设备变化
↓ 调用 kobject_uevent() 发送 uevent
↓
用户态 udev 通过 netlink 接收 uevent 消息
↓ 解析消息并匹配 udev 规则
↓ 执行规则(如加载驱动、创建设备节点)
通过这一机制,Linux 实现了硬件设备与用户态的自动交互,使得驱动加载、设备节点创建等过程对用户透明。
这和alias有关吗?
udev 自动加载驱动与 alias 有关。
在 Linux 系统中,模块安装时,depmod 程序会根据模块中的设备信息(如设备的 Vendor ID、Product ID 等)生成 modules.alias 文件。该文件位于 /lib/modules/$(uname -r)/ 目录下,其中记录了驱动模块的别名信息。
当内核检测到新设备并通过 uevent 机制将设备信息发送到用户态时,udevd 会根据 modules.alias 文件找到匹配的驱动模块。udevd 读取 uevent 中的设备信息,如设备的 Vendor ID、Product ID 等,然后在 modules.alias 文件中查找与之对应的驱动别名,从而确定需要加载的驱动模块,最后使用 modprobe 命令来加载驱动模块。
例如,对于一个 PCI 设备,其 Vendor ID 为 0x10EC,Device ID 为 0x8139,在模块安装时,depmod 会根据相关信息在 modules.alias 文件中生成对应的条目,当内核检测到该 PCI 设备时,udevd 就会根据 modules.alias 文件找到对应的驱动模块(如 8139too 模块)并加载。
有些系统中看到的kmod load
是什么?
kmod vs modprobe
kmod 是现代 Linux 系统(如 systemd 系统)中推荐使用的模块管理工具,而 modprobe 是传统工具。两者的主要区别:
kmod 与 udev 的协作流程
当 udev 接收到内核的 uevent 并决定加载驱动时,实际执行的流程通常是:
- udev 解析规则:根据设备信息(如 USB ID)匹配 udev 规则。
- 触发模块加载:通过执行 kmod load <模块名> 命令加载驱动。
- kmod 处理依赖:检查模块依赖关系,按顺序加载所有必要模块。
例如,udev 规则可能包含:
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", RUN+="/sbin/kmod load ftdi_sio"
从 systemd-udevd 运行 log 中研究其自动加载内核模块的过程
https://blog.csdn.net/Longyu_wlz/article/details/121109303
<包含许多相关链接>
https://www.cnblogs.com/WangYangkai/p/17012047.html
udev重新加载规则,重新触发事件
重新加载所有 udev 规则
若修改了 udev 规则,需先重新加载规则,再触发事件:
# 1. 重新加载 udev 规则
sudo udevadm control --reload-rules
# 2. 触发所有设备的事件
sudo udevadm trigger --action=add
调试与验证
- 使用 udevadm monitor 监控事件
在另一个终端中运行:
udevadm monitor
然后执行 udevadm trigger,观察输出是否包含预期的驱动加载事件。
查看initramfs中加载驱动:
查看当前系统initramfs中包含了哪些驱动:
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E "virtio_net"
如何打入驱动:
- 显示声明:
/etc/initramfs-tools/modules
- udev自动分析当前驱动
- hook脚本:在
/etc/initramfs-tools/hooks/
目录下创建可执行脚本
在 Linux 系统启动过程中,initramfs 中加载的驱动是否会保留在最终的内存中取决于多个因素。以下是详细解释:
一、initramfs 的生命周期与驱动加载机制
-
initramfs 的作用
initramfs 是一个临时根文件系统,在系统启动初期挂载,用于加载必要的驱动和工具,以便内核能够识别和挂载真正的根文件系统(如 /dev/sda1)。
一旦真正的根文件系统挂载成功,initramfs 通常会被卸载或释放,其内容不再被使用。 -
驱动加载的两种情况
情况 1:驱动在内核启动阶段被加载
若驱动在 initramfs 阶段被加载(如通过 /etc/initramfs-tools/modules 配置),且在根文件系统挂载后未被卸载,则驱动会保留在最终的内存中。
情况 2:驱动仅在 initramfs 阶段需要
某些驱动仅用于 initramfs 阶段的特定任务(如识别存储设备),根文件系统挂载后不再需要,可能被卸载。
二、驱动是否保留在最终内存中的关键因素
- 驱动是否被显式卸载
initramfs 脚本(如 /scripts/init-bottom)可能包含卸载驱动的逻辑。若依赖驱动在根文件系统挂载后被卸载,目标驱动将无法访问其符号。
解决方案:修改 initramfs 脚本,避免卸载关键驱动,或在根文件系统挂载后重新加载。