linux驱动的自动加载机制

yuanheci 2025年06月05日 20次浏览

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 是传统工具。两者的主要区别:
image-1749135702402

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

调试与验证

  1. 使用 udevadm monitor 监控事件
    在另一个终端中运行:
udevadm monitor

然后执行 udevadm trigger,观察输出是否包含预期的驱动加载事件。


查看initramfs中加载驱动:

查看当前系统initramfs中包含了哪些驱动:

lsinitramfs /boot/initrd.img-$(uname -r) | grep -E "virtio_net"

如何打入驱动:

  1. 显示声明:/etc/initramfs-tools/modules
  2. udev自动分析当前驱动
  3. hook脚本:在 /etc/initramfs-tools/hooks/ 目录下创建可执行脚本

在 Linux 系统启动过程中,initramfs 中加载的驱动是否会保留在最终的内存中取决于多个因素。以下是详细解释:

一、initramfs 的生命周期与驱动加载机制

  1. initramfs 的作用
    initramfs 是一个临时根文件系统,在系统启动初期挂载,用于加载必要的驱动和工具,以便内核能够识别和挂载真正的根文件系统(如 /dev/sda1)。
    一旦真正的根文件系统挂载成功,initramfs 通常会被卸载或释放,其内容不再被使用。

  2. 驱动加载的两种情况
    情况 1:驱动在内核启动阶段被加载
    若驱动在 initramfs 阶段被加载(如通过 /etc/initramfs-tools/modules 配置),且在根文件系统挂载后未被卸载,则驱动会保留在最终的内存中。
    情况 2:驱动仅在 initramfs 阶段需要
    某些驱动仅用于 initramfs 阶段的特定任务(如识别存储设备),根文件系统挂载后不再需要,可能被卸载。

二、驱动是否保留在最终内存中的关键因素

  1. 驱动是否被显式卸载
    initramfs 脚本(如 /scripts/init-bottom)可能包含卸载驱动的逻辑。若依赖驱动在根文件系统挂载后被卸载,目标驱动将无法访问其符号。
    解决方案:修改 initramfs 脚本,避免卸载关键驱动,或在根文件系统挂载后重新加载。