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二进制"微信公众号
评论
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 138浏览
  • TOF多区传感器: ND06   ND06是一款微型多区高集成度ToF测距传感器,其支持24个区域(6 x 4)同步测距,测距范围远达5m,具有测距范围广、精度高、测距稳定等特点。适用于投影仪的无感自动对焦和梯形校正、AIoT、手势识别、智能面板和智能灯具等多种场景。                 如果用ND06进行手势识别,只需要经过三个步骤: 第一步&
    esad0 2024-12-04 11:20 103浏览
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 114浏览
  • 遇到部分串口工具不支持1500000波特率,这时候就需要进行修改,本文以触觉智能RK3562开发板修改系统波特率为115200为例,介绍瑞芯微方案主板Linux修改系统串口波特率教程。温馨提示:瑞芯微方案主板/开发板串口波特率只支持115200或1500000。修改Loader打印波特率查看对应芯片的MINIALL.ini确定要修改的bin文件#查看对应芯片的MINIALL.ini cat rkbin/RKBOOT/RK3562MINIALL.ini修改uart baudrate参数修改以下目
    Industio_触觉智能 2024-12-03 11:28 110浏览
  • 概述 说明(三)探讨的是比较器一般带有滞回(Hysteresis)功能,为了解决输入信号转换速率不够的问题。前文还提到,即便使能滞回(Hysteresis)功能,还是无法解决SiPM读出测试系统需要解决的问题。本文在说明(三)的基础上,继续探讨为SiPM读出测试系统寻求合适的模拟脉冲检出方案。前四代SiPM使用的高速比较器指标缺陷 由于前端模拟信号属于典型的指数脉冲,所以下降沿转换速率(Slew Rate)过慢,导致比较器检出出现不必要的问题。尽管比较器可以使能滞回(Hysteresis)模块功
    coyoo 2024-12-03 12:20 170浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 143浏览
  • 11-29学习笔记11-29学习笔记习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-02 23:58 92浏览
  • 当前,智能汽车产业迎来重大变局,随着人工智能、5G、大数据等新一代信息技术的迅猛发展,智能网联汽车正呈现强劲发展势头。11月26日,在2024紫光展锐全球合作伙伴大会汽车电子生态论坛上,紫光展锐与上汽海外出行联合发布搭载紫光展锐A7870的上汽海外MG量产车型,并发布A7710系列UWB数字钥匙解决方案平台,可应用于数字钥匙、活体检测、脚踢雷达、自动泊车等多种智能汽车场景。 联合发布量产车型,推动汽车智能化出海紫光展锐与上汽海外出行达成战略合作,联合发布搭载紫光展锐A7870的量产车型
    紫光展锐 2024-12-03 11:38 126浏览
  •         温度传感器的精度受哪些因素影响,要先看所用的温度传感器输出哪种信号,不同信号输出的温度传感器影响精度的因素也不同。        现在常用的温度传感器输出信号有以下几种:电阻信号、电流信号、电压信号、数字信号等。以输出电阻信号的温度传感器为例,还细分为正温度系数温度传感器和负温度系数温度传感器,常用的铂电阻PT100/1000温度传感器就是正温度系数,就是说随着温度的升高,输出的电阻值会增大。对于输出
    锦正茂科技 2024-12-03 11:50 141浏览
  • 作为优秀工程师的你,已身经百战、阅板无数!请先醒醒,新的项目来了,这是一个既要、又要、还要的产品需求,ARM核心板中一个处理器怎么能实现这么丰富的外围接口?踌躇之际,你偶阅此文。于是,“潘多拉”的魔盒打开了!没错,USB资源就是你打开新世界得钥匙,它能做哪些扩展呢?1.1  USB扩网口通用ARM处理器大多带两路网口,如果项目中有多路网路接口的需求,一般会选择在主板外部加交换机/路由器。当然,出于成本考虑,也可以将Switch芯片集成到ARM核心板或底板上,如KSZ9897、
    万象奥科 2024-12-03 10:24 96浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦