Linux驱动|modprobe加载oot驱动与重启系统后自动加载oot驱动分析总结

原创 Linux二进制 2023-11-19 08:20

一、前言

在做Linux驱动开发及调试的过程中,经常会遇到需要手动修改及编译驱动源代码、加载编译出来的oot驱动的情况。刚开始做Linux驱动开发的时候,老员工告诫我在调试驱动的时候,最好用insmod来加载自己编译的oot驱动,这样既方便又安全。

为什么这么说呢?因为我在用modprobe nfp加载自己编译的oot驱动时,每次发现其加载的驱动文件均为/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/文件夹下面由内核自带的in-tree驱动文件,而并非我手动编译出来的oot驱动文件。于是,查询了一下modprobe用法,发现modprobe默认会去/lib/modules/$(uname -r)/下面查找待加载的module,因此,就想到将/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/下面的驱动文件每次替换为自己编译出来的oot驱动文件,这样就可以成功加载自己编译的驱动了。

于是,就对/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/ 路径下的in-tree驱动文件备份,并用我手动编译出来的驱动文件替换该路径下的驱动文件。本以为这种方式很nice,结果老员工却告诉我当我编译出来的oot驱动文件有bug的时候,即使重新启动系统,原本的驱动也无法恢复,导致设备工作异常;因为该路径下原有的in-tree驱动文件已不存在,而使用insmod直接加载我编译出来的oot驱动时,即使该驱动文件有bug,系统重启后,依然可以通过使用/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/路径下的in-tree驱动文件正常启动系统。

想一想,好像确实是这个道理,于是,在日后的工作中,但凡加载自己手动编译的oot驱动,我都是使用insmod命令。但是,后续的工作中,又遇到了一个问题,就是使用insmod加载的驱动,在系统重新启动后,又变成了系统自带的in-tree驱动。于是,只能再次手动卸载in-tree驱动,再加载oot驱动。如果该主机上部署了与该oot驱动模块紧密相关的业务环境,意味着一切将需要重新手动设置一遍,不可谓不麻烦。于是乎,系统重启后自动加载oot驱动就成了一个亟待解决的问题。

因此,遂考虑可能是因为使用insmod加载驱动的缘故,导致系统重新启动后无法自动加载oot驱动。于是,便研究如何在工作中通过modprobe来加载oot驱动。

注意:其实导致系统重新启动后无法自动加载oot驱动,与使用insmodmodprobe加载没有关系,后续内容会讲解。

拓展】:模块依据代码编写与编译时的位置可分:内部模块和外部模块,即 in-tree模块 和 out-of-tree(即oot)模块,在内核树外部编写并构建的模块就是外部模块。动态加载的模块包括in-tree模块和out-of-tree(oot)模块。in-tree 模块是 Linux 内核树的内部自带的模块,即它们已经是内核的一部分。树外模块是 来自 Linux 内核树的外部。它们通常是为开发和测试目的编写的,例如测试树级或处理不兼容的内核模块的新版本。往往oot模块虽然安装成功了,但是会提示loading out-of-tree module taints kernel,可通过dmesg查看到。

经过针对 modprobe 的研究和实验,本文总结三种方法:拷贝法、软链接法和配置 external 路径法。

注意:本文所有实验均在CentOS Stream 8系统上进行,一切配置和命令仅适用于CentOS系列机器,Ubuntu与其他机器具体配置指令可能有所区别。

二、modprobe加载oot驱动总结

这里有关modprobe的使用总结的三种方法,均需要依赖/etc/depmod.d/下的配置文件来实现自动识别驱动加载路径。/etc/depmod.d/下通常会含有如下配置文件:

[root@localhost ~]# ls -l /etc/depmod.d/
total 8
-rw-r--r--. 1 root root 116 Jun 5 2021 dist.conf
-rw-r--r--. 1 root root 115 Nov 10 2021 kvdo.conf

接下来,让我们一起了解一下有关使用modprobe的三种方法。

1、拷贝法

将自己编译生成的oot驱动文件拷贝到/lib/modules/$(uname -r)/extra/目录下,再执行echo "override xxx * extra" > /etc/depmod.d/xxx.conf命令,确保当Linux内核中存在多个同名的内核模块时,优先安装/lib/modules/$(uname -r)/extra/目录下的文件。随后,再执行depmod -a 进行模块依赖的更新(驱动如果存在依赖项,必须先加载依赖项后才能进行驱动的安装)。

注意echo "override xxx * extra" > /etc/depmod.d/xxx.conf 命令表示在/etc/depmod.d/目录下创建一个 xxx.conf(名字任意)文件,在里面添加override xxx * extra(其中,xxx表示待加载的驱动名字(不带.ko后缀),*表示匹配任何内核版本,也可以指定具体的内核版本),通过/etc/depmod.d目录内的配置文件,设置override命令,确保安装在 /lib/modules/$(uname -r)/extra/(或其他模块位置)下的任何匹配模块名称将优先于内核已经提供的任何类似名称的模块。外部开发的模块一般我们都放在/lib/modules/$(uname -r)/extra 目录下使用

拓展】:depmod配置文件的override命令格式和解析如下:

override modulename kernelversion modulesubdirectory     

This command allows you to override which version of a specific module will be used when more than one module sharing the same name is processed by the depmod command. It is possible to specify one kernel or all kernels using the * wildcard. modulesubdirectory is the name of the subdirectory under /lib/modules (or other module location) where the target module is installed. For example, it is possible to override the priority of an updated test module called kmod by specifying the following command: "override kmod * extra". This will ensure that any matching module name installed under the extra subdirectory within /lib/modules (or other module location) will take priority over any likenamed module already provided by the kernel.

实战演示如下:

# 将自己编译的oot nfp驱动拷贝到/lib/modules/$(uname -r)/extra/路径下
[root@localhost ~]# cp /home/xxx/nfp-drv-kmods-private/src/nfp.ko /lib/modules/$(uname -r)/extra/nfp.ko
[root@localhost ~]# ls -l /lib/modules/$(uname -r)/extra
total 50900
-rw-r--r--. 1 root root 52121240 Nov 15 19:49 nfp.ko
# 如果/etc/下不存在depmod.d目录,则执行如下命令创建depmod.d目录,否则无需执行
[root@localhost ~]# mkdir -p /etc/depmod.d
# 该命令确保在depmod命令处理多个共享相同名称的内核模块时,优先安装/lib/modules/$(uname -r)/extra/下的模块
[root@localhost ~]# echo "override nfp * extra" > /etc/depmod.d/nfp.conf
# 探测所有模块。如果在命令行中没有给出文件名,则默认启用此选项。
[root@localhost ~]# depmod -a
# depmod创建一个模块依赖列表,并确定它导出了什么符号以及它需要什么符号。默认情况下,该列表被写入modules.dep
[root@localhost ~]# cat /lib/modules/$(uname -r)/modules.dep | grep nfp
extra/nfp.ko:
[root@localhost ~]#
# 系统自带in-tree nfp驱动,显示大小为442368字节
[root@localhost ~]# lsmod | grep nfp
nfp 442368 0
tls 110592 1 nfp
# 卸载系统自带的in-tree nfp驱动
[root@localhost ~]# rmmod nfp
# 直接modprobe nfp就会加载手动编译的oot nfp驱动
[root@localhost ~]# modprobe nfp
# 手动编译的oot nfp驱动,显示大小为585728字节
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0
# 将depmod -a更新后的结果保存到initramfs中,这一步可选
[root@localhost ~]# dracut -f

根据上面的结果,可以看出来拷贝法需要将手动编译的oot驱动复制到/lib/modules/$(uname -r)/extra目录下,创建depmod的配置文件,即/etc/depmod.d/nfp.conf,使用depmod创建模块依赖列表,再使用modprobe加载驱动的时候,就可以成功安装我们手动编译的oot驱动了。这里之所以将oot驱动复制到extra目录下,是为了更新依赖列表后就可以使用modprobe成功安装,因为执行了echo "override nfp * extra" > /etc/depmod.d/nfp.conf这一步,override命令确保安装在 /lib/modules/$(uname -r)/extra/下的nfp 驱动将优先于内核已经提供的任何同名的模块。

上面实战演示中的dracut -f是可选的步骤,可以执行,也可以不执行。具体作用后面再详细介绍。

2、软链接法

软链接法与拷贝法比较相似,区别仅在于将自己编译生成的 oot 驱动文件通过建立软链接链接到 /lib/modules/$(uname -r)/extra/ 目录下,而非拷贝到 extra 目录下,其余步骤与拷贝法基本相同。

注意uname -r 是获取系统当前使用的内核版本,不同内核版本有各自的内核目录。

实战演示如下:

[root@localhst ~]# rm -f /lib/modules/$(uname -r)/extra/nfp.ko
[root@localhost ~]# ls -l /lib/modules/$(uname -r)/extra
total 0
# 建立软链接
[root@localhost ~]# ln -sf /home/xxx/nfp-drv-kmods-private/src/nfp.ko /lib/modules/$(uname -r)/extra/nfp.ko
[root@localhost ~]# ls -l /lib/modules/$(uname -r)/extra
total 0
lrwxrwxrwx. 1 root root 42 Nov 16 12:20 nfp.ko -> /home/xxx/nfp-drv-kmods-private/src/nfp.ko
# 因拷贝法中已创建并配置该文件,因此,这里直接使用即可。否则,需要创建并配置该文件内容如下
[root@localhost ~]# cat /etc/depmod.d/nfp.conf
override nfp * extra
# 创建依赖列表
[root@localhost ~]# depmod -a
# 卸载掉之前安装的驱动模块
[root@localhost ~]# rmmod nfp
# 安装手动编译的oot nfp驱动
[root@localhost ~]# modprobe nfp
# 查看新加载的oot nfp驱动
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0
# 将depmod -a更新后的结果保存到initramfs中,这一步可选
[root@localhost ~]# dracut -f

根据上面的结果,可以看出来软链接法需要将手动编译的oot驱动链接到/lib/modules/$(uname -r)/extra目录下,创建并配置depmod的配置文件,再使用depmod创建模块依赖列表。当使用modprobe加载驱动的时候,就可以成功安装我们手动编译的oot驱动了。这里之所以将oot驱动软链接到extra目录下,更新依赖列表后就可以使用modprobe成功安装,是因为创建并配置了depmod的配置文件,override命令确保安装在 /lib/modules/$(uname -r)/extra/下的nfp 驱动将优先于内核已经提供的任何同名的模块。

上面实战演示中的dracut -f是可选的步骤,可以执行,也可以不执行。具体作用后面再详细介绍。

3、配置external路径

【解析】使用external关键字,可以指定系统上的任意编译生成oot驱动的目录作为modprobe安装驱动的路径。

配置external路径法无需将自己编译生成的oot驱动文件拷贝或者建立软链接到/lib/modules/$(uname -r)/extra/目录下,但是需执行echo "external * /home/xxx/nfp-drv-kmods-private/src" > /etc/depmod.d/xxx.conf命令以及配置/etc/depmod.d/dist.conf 文件。随后,再执行depmod -a 进行模块依赖表的更新,即更新modules.depmodules.dep.bin文件。这时,再进行modprobe的时候,直接安装的则是通过external命令指定的路径下的oot驱动。

注意echo "external * /home/xxx/nfp-drv-kmods-private/src" > /etc/depmod.d/xxx.conf 命令表示在/etc/depmod.d/目录下创建一个 xxx.conf(名字任意)文件,在里面添加external * /home/xxx/nfp-drv-kmods-private/src(其中,/home/xxx/nfp-drv-kmods-private/src为编译出oot驱动的路径(xxx表示一个实际的路径名字而已), *表示匹配任何内核版本,也可以指定具体的内核版本),通过/etc/depmod.d目录内的配置文件,设置external命令,表示这是一个外部的路径。/etc/depmod.d/dist.conf的内容则表示搜索路径的优先级,如果想优先匹配external指定的路径下的文件,则需将external放在extrabuilt-in之前。这样external指定的路径下的任何匹配模块名称将优先于extra内保存的同名模块和内核已经提供的同名模块。

拓展】:depmod配置文件的external命令格式和解析如下:

external kernelversion absolutemodulesdirectory...

This specifies a list of directories, which will be checked according to the priorities in the search command. The order matters also, the first directory has the higher priority. The kernelversion is a POSIX regular expression or * wildcard, like in the override.

实战演示如下:

# 创建并配置depmod配置文件auto_define.conf
[root@localhost ~]# echo "external * /home/xxx/nfp-drv-kmods-private/src" > /etc/depmod.d/auto_define.conf
[root@localhost ~]# cat /etc/depmod.d/auto_define.conf
external * /home/xxx/nfp-drv-kmods-private/src
[root@localhost ~]# ls -l /etc/depmod.d/
auto_define.conf dist.conf kvdo.conf
# 编辑dist.conf文件内容,使external指定的路径优先级高于extra和built-in,即将external放在extra和built-in前面
[root@localhost ~]# vi /etc/depmod.d/dist.conf
# 查看dist.conf文件内容
[root@localhost ~]# cat /etc/depmod.d/dist.conf
#
# depmod.conf
#

# override default search ordering for kmod packaging
search updates external extra built-in weak-updates
# 创建依赖列表
[root@localhost ~]# depmod -a
# 查看modules.dep内容,根据检索结果可知,加载驱动使用的是/home/xxx/nfp-drv-kmods-private/src/路径下的oot nfp驱动
[root@localhost ~]# cat /lib/modules/4.18.0-500.el8.x86_64/modules.dep | grep nfp.ko
/home/xxx/nfp-drv-kmods-private/src/nfp.ko:
# 卸载掉系统上原有已加载的驱动
[root@localhost ~]# rmmod nfp
# 重新加载驱动
[root@localhost ~]# modprobe nfp
[root@localhost ~]#
# oot nfp驱动加载成功
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0
# 将depmod -a更新后的结果保存到initramfs中,这一步可选
[root@localhost ~]# dracut -f

需要注意的是:因为在/etc/depmod.d/dist.conf中,external的优先级高于extra,因此使用modprobe的时候,优先加载的是external 指定路径下的驱动文件。否则,如果dist.conf的内容如下所示:

[root@localhost ~]# cat /etc/depmod.d/dist.conf
#
# depmod.conf
#

# override default search ordering for kmod packaging
search updates extra external built-in weak-updates

extra位于external之前,则modprobe的时候,优先加载的将是/lib/modules/$(uname -r)/extra/目录下的驱动文件。

注意built-in表示/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/目录。

三、重启系统后自动加载oot驱动

在日常Linux驱动开发及调试的过程中,经常遇到需要手动加载oot驱动成功的情况下,一旦重启系统以后,机器上重启前已成功加载的驱动就不见了,又需要重新再手动加载一遍,要是上面部署着复杂的业务,则全部都需要再重新部署一遍,就极其麻烦了。于是乎,系统重启后自动加载oot驱动就成了一个亟待解决的问题。针对这个问题,小编经过学习以及工作中实战,终于摸索出这里面的规律,总结如下:

  • 规律一:无论是使用insmodmodprobe 加载驱动,如果未执行dracut --force 指令,均有可能会出现重启系统后系统中原来加载的oot驱动消失,被in-tree驱动替代的现象。

  • 规律二:如果initramfs中包含相关驱动且系统硬盘驱动库目录下存在同名的驱动,则系统重启时,会加载initramfs中的该驱动(in-treeoot 均适用)。

  • 规律三:如果initramfs中包含多个同名驱动(in-treeoot),则会根据这些同名驱动的优先级(/etc/depmod.d/dist.conf中含有优先级),系统启动时选择优先级最高的驱动加载。

  • 规律四:如果initramfs中不包含相关驱动,而系统硬盘驱动库下存在同名的驱动,则系统启动时会选择系统硬盘驱动库目录下的该同名驱动加载。

拓展initramfs 即 initram file system,翻译成中文意思就是 初始 ram 文件系统,基于 tmpfs,是一种大小灵活,直接作用在内存中的文件系统。initramfs包含的工具和脚本,在正式的根文件系统的初始化脚本 init 启动之前,就被挂载。Linux系统开机后,首先加载initramfs文件中包含的驱动程序,如果相应的设备对应的驱动不在initramfs文件包含范围内,那么会去系统硬盘存储的驱动库中去寻找匹配的驱动进行加载;系统硬盘驱动库的位置即为:/lib/modules/$($uname -r)/(下面讲系统硬盘驱动库时,即表示该目录);所以相应的驱动只要在系统硬盘的驱动库下或者initramfs中至少存在一个就可以正常加载,一旦在initramfs中加载成功,无论系统硬盘的驱动库中存在的驱动版本是否相同都不会重新去加载。initramfs中包含的驱动ko文件在目录lib/modules/下,具体包含的ko可依次查看。

针对上述总结的规律,让我们通过实战演示来验证一下。

1、规律一

无论是使用insmodmodprobe 加载驱动,如果未执行dracut --force 指令,均有可能会出现重启系统后系统中原来加载的oot驱动消失,被in-tree驱动替代的现象。

实战演示如下:

# 卸载掉系统中原来安装的nfp驱动
[root@localhost ~]# rmmod nfp
[root@localhost ~]# lsmod | grep nfp
[root@localhost ~]# ls -l /home/xxx/nfp-drv-kmods-private/src/ | grep nfp.ko
-rw-r--r--. 1 root root 52121240 Nov 17 19:10 nfp.ko
# insmod安装自己编译的oot nfp驱动
[root@localhost ~]# insmod /home/xxx/nfp-drv-kmods-private/src/nfp.ko
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0
# insmod安装完oot nfp驱动后,直接重启系统
[root@localhost ~]# reboot
# 重启系统后虽然加载了nfp驱动,但是并非自己编译的oot nfp驱动,而是系统内核自带的in-tree nfp驱动
[root@localhost ~]# lsmod | grep nfp
nfp 442368 0
tls 110592 1 nfp

通过对比系统重启前后,加载的nfp驱动的大小可以知道,前后加载的驱动并非同一个驱动。果然,如果未执行dracut --force 指令,系统启动后,系统内核自带的in-tree驱动会取代了我自己编译的oot驱动。那dracut --force指令的作用是什么呢?其实这个命令的作用就是将当前系统硬盘驱动库中包含的驱动写入到initramfs镜像中,该镜像会在系统启动过程中,将里面含有的相关驱动加载到系统中。让我们执行这个命令后,再看一下结果:

[root@localhost ~]# rmmod nfp
[root@localhost ~]# insmod /home/xxx/nfp-drv-kmods-private/src/nfp.ko
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0
# dracut -f为 dracut --force的缩写
[root@localhost ~]# dracut -f
[root@localhost ~]#
[root@localhost ~]# reboot
# 重启后,加载的是in-tree nfp驱动
[root@localhost ~]# lsmod | grep nfp
nfp 442368 0
tls 110592 1 nfp

明明前面说oot驱动加载后,未执行dracut --force,系统启动后,系统内核自带的in-tree驱动会取代了我自己编译的oot驱动。为什么我现在执行了这个命令,我编译的 oot 驱动却还是被系统内核自带的in-tree驱动取代了呢?因为dracut -f这个命令的作用是将当前系统硬盘驱动库中包含的驱动写入到initramfs镜像中,而我使用 insmod 加载的是我自己编译目录下的驱动,而系统硬盘驱动库中并未含有我编译的 oot 驱动,让我将自己编译的oot驱动放置到系统硬盘驱动库下属的extra目录下,再验证一下结果会是怎么样。

[root@localhost ~]# cd /lib/modules/$(uname -r)/extra/
[root@localhost extra]# ls
[root@localhost extra]# cp /home/xxx/nfp-drv-kmods-private/src/nfp.ko .
[root@localhost extra]# ls
nfp.ko
[root@localhost extra]# pwd
/lib/modules/4.18.0-500.el8.x86_64/extra
[root@localhost extra]# rmmod nfp
# insmod加载编译路径下的oot驱动
[root@localhost extra]# insmod /home/xxx/nfp-drv-kmods-private/src/nfp.ko
[root@localhost extra]# lsmod | grep nfp
nfp 585728 0
#建立模块依赖列表
[root@localhost extra]# depmod -a
# 将oot驱动复制到extra目录下以后,执行depmod -a果然更新了模块依赖列表
[root@localhost extra]# cat /lib/modules/$(uname -r)/modules.dep | grep nfp.ko
extra/nfp.ko:
# 更新initramfs镜像
[root@localhost extra]# dracut -f

# 拷贝initramfs到新创建的test1目录下
[root@localhost test1]# cp /boot/initramfs-4.18.0-500.el8.x86_64.img .
[root@localhost test1]# ls
initramfs-4.18.0-500.el8.x86_64.img
# 解压缩initramfs到新创建的test1目录下
[root@localhost test1]# /usr/lib/dracut/skipcpio ./initramfs-4.18.0-500.el8.x86_64.img | zcat | cpio -ivd
.
bin
dev
dev/console
dev/kmsg
dev/null
dev/random
dev/urandom
etc
......
[root@localhost test1]# ls
bin etc init lib opt root sbin sys tmp var
dev home initramfs-4.18.0-500.el8.x86_64.img lib64 proc run shutdown sysroot usr
# initramfs镜像的lib/modules/4.18.0-500.el8.x86_64/extra/目录下含有nfp.ko
[root@localhost test1]# ls ./lib/modules/4.18.0-500.el8.x86_64/extra/
nfp.ko

# 重新启动系统
[root@localhost test1]# reboot

#重启系统后,加载的是我自己编译的oot驱动
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0

果然,将自己编译的oot驱动放置到系统硬盘驱动库下属的extra目录下,执行depmod -a,再执行dracut -f,即会更新initramfs镜像,使其在initramfs镜像内的驱动库下属的extra目录下含有我编译的oot驱动,这样系统再重启以后,就会自动加载我编译的oot驱动了。因此,无论是使用insmodmodprobe加载oot驱动,重点是将自己编译的oot驱动放置到硬盘驱动库下属的相关目录下,执行depmod -a,再执行dracut -f,更新initramfs镜像,使其在initramfs镜像内的驱动库下属相关目录下含有我编译的oot驱动,这样系统再重启以后,就会自动加载我编译的oot驱动了。

这里,modprobe加载oot驱动的演示就不再给出,感兴趣的小伙伴可以自行尝试。

2、规律二

如果initramfs中包含相关驱动且系统硬盘驱动库目录下存在同名的驱动,则系统重启时,会加载initramfs中的该驱动(in-treeoot 均适用)。

实战演示如下:

# 创建test2目录,并将dracut -f生成的initramfs镜像拷贝到该目录下
[root@localhost test2]# cp /boot/initramfs-4.18.0-500.el8.x86_64.img .
[root@localhost test2]# ls
initramfs-4.18.0-500.el8.x86_64.img
# 解压initramfs镜像到当前目录下
[root@localhost test2]# /usr/lib/dracut/skipcpio ./initramfs-4.18.0-500.el8.x86_64.img | zcat | cpio -ivd
.
bin
dev
dev/console
dev/kmsg
......
[root@localhost test2]# ls
bin etc init lib opt root sbin sys tmp var
dev home initramfs-4.18.0-500.el8.x86_64.img lib64 proc run shutdown sysroot usr
# 解压的initramfs镜像的lib/modules/4.18.0-500.el8.x86_64/extra/目录下含有nfp.ko,该驱动为oot驱动
[root@localhost test1]# ls ./lib/modules/4.18.0-500.el8.x86_64/extra/
nfp.ko
# 系统硬盘驱动库目录下属目录中存在同名的驱动,该驱动为in-tree驱动
[root@localhost ~]# ls /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/
nfp.ko.xz
# 重启系统
[root@localhost ~]# reboot
# 根据nfp驱动的大小,可知重启后加载的驱动为oot驱动
[root@localhost ~]# lsmod | grep nfp
nfp 585728 0

根据实战演示的结果可知,当initramfs镜像和系统硬盘驱动库目录下存在同名的驱动时,重启操作系统后,加载的是位于initramfs镜像内的oot驱动。

3、规律三

如果initramfs中包含多个同名驱动(in-treeoot),则会根据这些同名驱动的优先级(/etc/depmod.d/dist.conf中含有优先级),系统启动时选择优先级最高的驱动加载。

实战演示如下:

[root@localhost ~]# vi /etc/depmod.d/dist.conf
[root@localhost ~]# vi /etc/depmod.d/auto_define.conf
[root@localhost ~]# cat /etc/depmod.d/auto_define.conf
external * /home/xxx/nfp-drv-kmods-private/src
# external位于extra和built-in之前,表示其优先级高于后两者
[root@localhost ~]# cat /etc/depmod.d/dist.conf
#
# depmod.conf
#

# override default search ordering for kmod packaging
search updates external extra built-in weak-updates

#更新模块依赖列表
[root@localhost ~]# depmod -a
# 查看模块依赖列表,优先级最高的是external设定的/home/xxx/nfp-drv-kmods-private/src/目录下的nfp驱动
[root@localhost ~]# cat /lib/modules/$(uname -r)/modules.dep | grep nfp
/home/xxx/nfp-drv-kmods-private/src/nfp.ko:
# 更新initramfs镜像
[root@localhost ~]# dracut -f

# 创建test3目录,并将dracut -f生成的initramfs镜像拷贝到该目录下
[root@localhost test3]# cp /boot/initramfs-4.18.0-500.el8.x86_64.img .
[root@localhost test3]# ls
initramfs-4.18.0-500.el8.x86_64.img
# 解压initramfs镜像到当前目录下
[root@localhost test3]# /usr/lib/dracut/skipcpio ./initramfs-4.18.0-500.el8.x86_64.img | zcat | cpio -ivd
.
bin
dev
dev/console
dev/kmsg
......
[root@localhost test3]# ls
bin etc init lib opt root sbin sys tmp var
dev home initramfs-4.18.0-500.el8.x86_64.img lib64 proc run shutdown sysroot usr
# initramfs镜像中含有/etc/depmod.d/auto_define.conf中定义的external目录下含义oot驱动
[root@localhost test3]# ls -l ./home/xxx/nfp-drv-kmods-private/src/ | grep nfp.ko
-rw-r--r--. 1 root root 52119640 Nov 18 21:51 nfp.ko
# initramfs镜像中含有驱动库目录下的in-tree驱动
[root@localhost test3]# ls ./lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/
nfp.ko.xz

# 重启系统
[root@localhost ~]# reboot
# 由已加载驱动的大小与前面均不同可知,加载的为external指定的目录下加载的oot驱动
[root@localhost ~]# lsmod | grep nfp
nfp 589824 0

根据实战演示结果可知,当initramfs中包含多个同名驱动(in-treeoot)时,则会根据这些同名驱动的优先级,选择优先级最高的驱动加载,无论其是in-treeoot驱动。

4、规律四

如果initramfs中不包含相关驱动,而系统硬盘驱动库下存在同名的驱动,则系统启动时会选择系统硬盘驱动库目录下的该同名驱动加载。

实战演示如下:

# 创建一个临时目录test4,存放initramfs镜像及解压后的文件
[root@localhost tmp]# mkdir test4
# 构造系统上不包含任何nfp驱动的当前内核对应的initramfs镜像并拷贝到test4目录下
[root@localhost test4]# cp /boot/initramfs-$(uname -r).img .
[root@localhost test4]# ls
initramfs-4.18.0-500.el8.x86_64.img

# 使用skipcpio解压缩当前目录下的initramfs镜像
[root@localhost test4]# /usr/lib/dracut/skipcpio ./initramfs-4.18.0-500.el8.x86_64.img | zcat | cpio -ivd
.
bin
dev
dev/console
dev/kmsg
dev/null
dev/random
dev/urandom
etc
etc/centos-release
etc/cmdline.d
etc/conf.d
etc/conf.d/systemd.conf
...
# 查看当前目录解压后包含的文件
[root@localhost test4]# ls
bin etc init lib opt root sbin sys tmp var
dev home initramfs-4.18.0-500.el8.x86_64.img lib64 proc run shutdown sysroot usr

# 查看解压后的initramfs中是否存在nfp驱动及依赖
[root@localhost test4]# cat ./lib/modules/4.18.0-500.el8.x86_64/modules.dep | grep nfp
# 解压后的initramfs中,连extra目录都不存在
[root@localhost test4]# ls -l ./lib/modules/4.18.0-500.el8.x86_64/extra/
ls: cannot access './lib/modules/4.18.0-500.el8.x86_64/extra/': No such file or directory
# 解压后的initramfs中,连lib/modules/4.18.0-500.el8.x86_64/kernel/drivers/net/ethernet/netronome/nfp/目录都不存在
[root@localhost test4]# ls -l ./lib/modules/4.18.0-500.el8.x86_64/kernel/drivers/net/ethernet/netronome/nfp/
ls: cannot access './lib/modules/4.18.0-500.el8.x86_64/kernel/drivers/net/ethernet/netronome/nfp/': No such file or directory

# 解压后的initramfs中,完全检索不到nfp.ko文件
[root@localhost test4]# find ./ -name "nfp.ko"
[root@localhost test4]#

# 查看当前系统驱动库下模块依赖列表/lib/modules/$(unaem -r)/modules.dep中是否包含nfp驱动
# 只有该列表中包含nfp驱动记录且硬盘驱动库下存在nfp驱动,在系统重启后,才能够成功加载硬盘上驱动库目录下的nfp驱动,
# 否则将不会加载nfp驱动。
[root@localhost ~]# cat /lib/modules/$(uname -r)/modules.dep | grep nfp
kernel/drivers/net/ethernet/netronome/nfp/nfp.ko.xz: kernel/net/tls/tls.ko.xz
# 检查系统硬盘驱动库下是否存在nfp驱动
[root@localhost ~]# ls -l /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/
total 176
-rw-r--r--. 1 root root 176228 Jun 28 08:17 nfp.ko.xz

# 卸载掉系统上当前安装的nfp驱动
[root@localhost ~]# rmmod nfp
# 重启操作系统
[root@localhost ~]# reboot

# 查看重启后的系统中是否成功加载nfp驱动,果然加载的是in-tree nfp驱动,即硬盘驱动目录下的nfp驱动
[root@localhost ~]# lsmod | grep nfp
nfp 442368 0
tls 110592 1 nfp

上述实战结果证明,initramfs 镜像中如果不包含相关驱动,而系统驱动库下的模块依赖列表中含有驱动依赖记录,且系统硬盘驱动库下属目录(即/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/)存在同名的驱动,则系统启动时会选择系统硬盘驱动库目录下属目录包含的该同名驱动进行加载。然而,如果系统驱动库下的模块依赖列表中不包含驱动依赖记录,则即使系统硬盘驱动库下属目录中含有相关驱动,操作系统亦不会加载。如下结果能够证明该结论。

[root@localhost ~]# cat /lib/modules/$(uname -r)/modules.dep | grep nfp
[root@localhost ~]#
[root@localhost ~]# ls -l /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/netronome/nfp/
total 176
-rw-r--r--. 1 root root 176228 Jun 28 08:17 nfp.ko.xz
[root@localhost ~]# rmmod nfp
[root@localhost ~]# lsmod | grep nfp
[root@localhost ~]# reboot
# 重启系统后,检查系统中是否含有nfp驱动,结果显示没有加载nfp驱动
[root@localhost ~]# lsmod | grep nfp
[root@localhost ~]#

至此,有关modprobe加载oot驱动与重启系统后自动加载oot驱动的分析就总结完毕了。俗话讲:“好记性不如烂笔头”;将相关知识总结成文,等日后有需要的时候可以拿出来快速回顾一下,当然这也有助于加深对这方面知识的理解。

最后,希望对于从事Linux驱动的朋友们有所帮助和启发。


Linux二进制 Linux编程、内核模块、网络原创文章分享,欢迎关注"Linux二进制"微信公众号
评论
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 68浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 74浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 82浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 96浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 88浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 82浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 88浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 96浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 112浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 87浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 77浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 102浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦