LV015-怎么加载
一、加载命令
前面我们已经拿到了 ko 文件,现在我们来学习一下怎么加载 ko 驱动。先来学习几个命令:
1. file——查看文件格式
file 命令可用于查看指定的.ko 文件可以用于哪种平台,一般使用格式如下:
file module_name.ko输出信息中,带 x86 字样的适用于主机 ubuntu linux,带 arm 字样的适用于开发板 linux。

2. dmesg——内核日志查看
dmesg 命令可用于查看内核的打印的提示信息,主要是在 Ubuntu 中加载模块的使用后使用,我们的开发板会实时在串口终端界面打提示信息,一般使用格式如下:
sudo dmesg -c # 清除内核已打印的信息
dmseg # 查看内核的打印信息3. 模块相关的命令
3.1 insmod——加载指定模块
insmod 命令可用于加载.ko 文件,一般使用格式如下:
insmod module_name.ko3.2 lsmod——查看已经加载的模块
lsmod 命令可用显示已经加载的模块,一般使用格式如下:
lsmod module_name.ko3.3 rmmod——卸载已经加载的模块
rmmod 命令可用于卸载已经加载的模块,一般使用格式如下:
rmmod module_name4. 加载测试
4.1 获取内核模块文件
上一节我们编译了两个内核模块文件,一个是在内核源码中编译的,另一个是在内核源码外编译的,这两个文件可以在这里找:02_module_load/module_load_test

4.2 拷贝到根文件系统
我们前面配置的开发环境是从 nfs 挂载根文件系统,所以我们直接把这两个内核模块文件拷贝到根文件系统去就行了,linux 系统启动后,我们就可以看到。
mkdir ~/4nfs/imx6ull_rootfs/driver_demo
cp -rvf module_load_test ~/4nfs/imx6ull_rootfs/drivers_demo/我们启动开发板,然后看一下/driver_demo 目录:

需要注意的事这里并不是所有的移植完的根文件系统都有 tree 命令,有的话就能用。另外我发现好像加载有些延迟,拷贝完,linux 开发板上还没有这些文件,等待一小会就好了。
4.3 模块测试
注意,两个测试模块名字一样,就不要同时加载了,一个测试完卸载后再加载另一个测试。命令都是一样的。
cd /drivers_demo
insmod hello_world_demo.ko # 加载模块
lsmod # 查看已加载模块
rmmod hello_world_demo # 卸载已加载的模块
二、modprobe
还有一个很强大的命令就是 modprobe,使用它,我们可以不进入驱动所在的目录。
1. 一个错误的解决
1.1 原因分析
还记得前边使用 buildroot 构建根文件系统的时候,有一个报错:

这里的这个目录起始就是为 modprobe 这个命令准备的,这个目录中将会存放驱动文件,然后可以不进入此目录,就直接使用 modprobe 命令加载指定的驱动。
“/lib/modules”这个目录是通用的,不管用的什么板子、什么内核,这部分是一样的。不一样的是这个目录下的子目录,会有一个以内核版本命名的目录,这个目录才是最终存放驱动的目录,例如“/lib/modules/4.19.71”,这里要根据我们所使用的 Linux 内核版本来设置,比如 ALPHA 开发板现在用的是 4.19.71 版本的 Linux 内核,因此就是“/lib/modules/4.19.71”。如果使用的其他版本内核,比如 5.14.31,那么就应该创建“/lib/modules/5.14.31”目录,否则 modprobe 命令无法加载驱动模块。
所以我们先自行在根文件系统创建这个目录,这个目录名怎么确定?我们可以看开机打印信息:

或者制作的根文件系统支持 uname 命令的话也可以使用这个命令来看:
uname -r
我们手动创建这个目录
mkdir -p /lib/modules/4.19.71-00007-g51f3cd8ec-dirty之后就会发现这个报错就会消失,但是又会报另一个错:

可以看出, modprobe 提示无法打开“modules.dep”这个文件,因此驱动挂载失败了。我们不用手动创建 modules.dep 这个文件,直接输入 depmod 命令即可自动生成 modules.dep。
1.2 添加 depmod 命令
有些根文件系统可能没有 depmod 这个命令,如果没有这个命令就只能重新配置 busybox 了,所以我们可以进入 buildroot 源码(我用的是这个)中,执行以下命令打开 busybox 的配置窗口:
cd ~/7Linux/buildroot-2023.05.1
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- busybox-menuconfig这里要加个 sudo,不然有个地方会报没有权限,反正我的是这样的。然后就会打开 busybox 的配置窗口。我们按以下配置项路径找一下 depmod 的配置项:
Linux Module Utilities --->
[*] depmod (27 kb)勾选这个 depmod:
BusyBox 1.36.1 Configuration
──────────────────────────────────────────────────────────────────────────────
┌──────────────────────── Linux Module Utilities ─────────────────────────┐
│ Arrow keys navigate the menu. <Enter> selects submenus --->. │
│ Highlighted letters are hotkeys. Pressing <Y> includes, <N> excludes, │
│ <M> modularizes features. Press <Esc><Esc> to exit, <?> for Help, </> │
│ for Search. Legend: [*] built-in [ ] excluded <M> module < > │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │[ ] Simplified modutils │ │
│ │[*] depmod (27 kb) │ │
│ │[*] insmod (22 kb) │ │
│ │[*] lsmod (1.9 kb) │ │
│ │[*] Pretty output │ │
│ │[ ] modinfo (24 kb) │ │
│ │[*] modprobe (28 kb) │ │
│ │[ ] Blacklist support │ │
│ │[*] rmmod (3.3 kb) │ │
│ │--- Options common to multiple modutils │ │
│ │[*] Accept module options on modprobe command line │ │
│ │[ ] Support version 2.2/2.4 Linux kernels │ │
│ │[*] Support tainted module checking with new kernels │ │
│ │[ ] Try to load module from a mmap'ed area │ │
│ │[*] Support module.aliases file │ │
│ │[*] Support module.symbols file │ │
│ │(/lib/modules) Default directory containing modules │ │
│ │(modules.dep) Default name of modules.dep │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────────────┤
│ <Select> < Exit > < Help > │
└─────────────────────────────────────────────────────────────────────────┘看最后两个配置项,我们应该是可以在这里自定义这个模块默认存放的目录以及 modules.dep 的默认文件名,不过这里还是默认好了。最后我们保存退出。然后我们执行以下命令重新编译:
sudo make # 在图形界面已经配置过编译工具链了1.3 重启测试
最后重启,就会发现还在报,原来是还需要用这个命令自动生成一些文件,我们直接在终端执行 depmod,就会生成下图这些文件:
depmod然后我们再重启,应该就不会有这些报错了:
2. 加载驱动
我们前边知道可以用 insmod 命令加载驱动,但是这个命令有一个缺点,就是驱动若是依赖其他驱动的话,就需要先加载其他依赖的驱动,然后这个驱动才能加载成功,这样是有些麻烦的,而且还需要指定驱动路径或者到驱动存放目录下才能加载。我们可以吧驱动放在上面创建的目录下:
cp drivers_demo/module_load_test/outside /lib/modules/4.19.71-00007-g51f3cd8ec-dirty/ -r然后我们直接在根目录执行:
modprobe hello_world_demo.ko然后会有以下信息:

从图中可以看出,报错了,第一次并未加载成功,这个时候我们需要执行一次 depmod 命令重新生成一下那几个文件:
ls /lib/modules/`uname -r` -F更新完毕后重新加载就可以了:

重新生成后,就可以成功加载驱动啦。
3. 命令说明
上面我们已经把问题解决,也体验了这个命令,接下来我们来学习一下这个命令的使用。
3.1 命令格式
我们可以直接在 ubuntu 下看一下 man 手册:
NAME
modprobe - Add and remove modules from the Linux Kernel
SYNOPSIS
modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] [modulename] [module parameters...]
modprobe [-r] [-v] [-n] [-i] [modulename...]
modprobe [-c]
modprobe [--dump-modversions] [filename]modprobe 会从 linux 内核中智能地添加或者移除模块。modprobe 需要一个实时更新的 modules.dep 文件,这个文件位于这里:
/lib/modules/`uname -r`/modules.dep这个文件由 depmod 命令生成。这个文件列出了每个模块还需要依赖哪些其他的模块。 modprobe 利用这个文件来自动解决添加和删除模块时候的依赖关系。我们可以看一下 bulidroot 创建的根文件系统中这个命令的手册:
BusyBox v1.36.1 (2024-11-02 20:28:53 CST) multi-call binary.
Usage: modprobe [-alrqvsD] MODULE [SYMBOL=VALUE]...
-a Load multiple MODULEs
-l List (MODULE is a pattern)
-r Remove MODULE (stacks) or do autoclean
-q Quiet
-v Verbose
-s Log to syslog
-D Show dependenciesmodprobe 命令在加载驱动模块的时候, 会同时加载该模块依赖的其他模块。 比如 helloworld.ko 依赖 before.ko,使用 insmod 加载的时候, 就必须先加载 before.ko, 然后在加载 helloworld.ko 才可以加载成功。 但是使用 modprobe 加载的时候, 他会自动分析模块的依赖关系, 然后将所有的依赖的模块都加载到内核当中。 比较“聪明” 。
同样, 在卸载驱动模块的时候, 如果模块存在依赖关系, 如果使用 insmod 命令, 需要手动卸载依赖的内核模块, 但是使用 modprobe 命令可以自动卸载驱动模块所依赖的其他模块。所以, 如果驱动模块是以“modprobe helloworld.ko”命令加载的, 卸载的时候使用“modprobe -r helloworld.ko” 命令卸载。但是使用 modprobe 卸载存在一个问题, 如果所依赖的模块被其他模块所使用, 这时候就不能使用 modprobe 卸载。 所以还是推荐使用 rmmod 命令来卸载。
3.1 modprobe -l
这个命令可以列出内核中所有已经或者未挂载的所有模块
modprobe -l3.2 modprobe -r
前面我们知道了怎么加载驱动,怎么卸载呢?可以用这个命令:
modprobe -r MODULE移除已加载的模块,和 rmmod 功能类似。注意:模块名是不能带有后缀的,我们通过 modprobe -l 所看到的模块,都是带有 .ko 或 .o 后缀。前面已经说了,当要卸载的模块依赖于别的模块的时候可能就会有问题,所以卸载的时候其实不是很常用这个命令,主要还是用的 rmmod。
3.3 modprobe -D
这个命令是显示依赖:
modprobe -D MODULE4. 搜索目录
在 Linux 中,modprobe 命令会在下面的路径搜索可加载的内核模块:
/lib/modules/`uname -r` #(内核模块所在的默认目录)uname -r 为当前系统所使用的内核版本。当我们使用 modprobe 命令加载一个内核模块时,系统首先会在上面的路径中搜索是否存在该模块,若存在,系统会将其加载到内存中。若以上三个路径都没有找到该模块,则系统会返回“找不到该模块”的错误。
我们可以通过 modprobe 配置文件来设置搜索路径。Linux 中 modprobe 的配置文件为/etc/modprobe.conf 和/etc/modprobe.d/,其中/etc/modprobe.conf 为全局配置文件,而/etc/modprobe.d/为目录,其中存放的是单独的模块配置文件。
在打开的 modprobe.conf 文件中,我们可以设定模块搜索路径,例如:
install 模块名 路径其实在前面打开 depmod 命令的时候,我们看到是可以直接在 buildroot 中配置目录的:

这里我就没做具体尝试了,感觉目前好像也不是很重要,后面有需要再补充吧。