Linux内核模块加载与卸载

一、核心概念:什么是内核模块?

内核模块(Kernel Module)是 Linux 内核的一种可动态加载/卸载的扩展组件。它们允许在不重新编译整个内核的情况下,为系统添加新的硬件支持、文件系统或内核功能。模块通常以 .ko(Kernel Object)为扩展名。

主要优势

  • 灵活性:按需加载,减少内核内存占用。
  • 可维护性:更新驱动或功能时无需重启系统。
  • 模块化:保持内核核心精简,通过模块扩展功能。

二、模块管理工具对比

Linux 提供了两套工具来管理内核模块,各有其适用场景。

工具 命令 特点 适用场景
智能管理工具 modprobe 1. 自动处理模块依赖关系
2. 使用模块名(无需路径)
3. 从标准模块目录搜索
日常使用首选,特别是加载复杂驱动
基础加载工具 insmod 1. 需指定模块完整路径
2. 不处理依赖关系
3. 直接系统调用
低级操作,调试或已知无依赖的简单模块
基础卸载工具 rmmod 1. 使用模块名卸载
2. 不处理依赖关系
卸载由 insmod 加载的模块
查看工具 lsmod 显示当前已加载的所有模块 状态检查

三、使用 modprobe(推荐方法)

modprobe 是智能化的模块管理工具,它会读取 /lib/modules/$(uname -r)/modules.dep 文件中的依赖关系,自动加载所需的所有模块。

3.1 准备工作:生成模块依赖关系

在首次使用或安装新模块后,建议先更新模块依赖数据库:

1
sudo depmod -a

此命令会扫描 /lib/modules/$(uname -r)/ 目录下的所有模块,生成 modules.dep 文件,其中记录了模块间的依赖关系。

3.2 加载模块

1
2
3
4
5
# 加载指定模块(自动处理依赖)
sudo modprobe vfat

# 加载所有模块(不常用)
sudo modprobe -a

注意:只需提供模块名(如 vfat),无需 .ko 后缀和路径。

3.3 卸载模块

1
2
# 卸载指定模块(自动尝试卸载依赖模块)
sudo modprobe -r vfat

3.4 常用 modprobe 参数详解

参数 功能
-a, --all 加载所有模块。
-r, --remove 卸载指定模块。
-l, --list 列出所有可用模块(带完整路径)。
-c, --show-conf 显示所有模块的配置信息(如别名)。
-d, --debug 启用调试模式。
-v, --verbose 显示详细执行信息。
--help 显示帮助信息。

3.5 实用示例

1
2
3
4
5
6
7
8
9
10
# 1. 查看模块配置信息(如别名)
sudo modprobe -c | grep vfat
# 输出示例:alias fs-vfat vfat

# 2. 列出所有可用模块
sudo modprobe -l
# 输出示例:/lib/modules/5.4.0-xx/kernel/fs/vfat/vfat.ko

# 3. 带详细信息加载模块
sudo modprobe -v vfat

四、使用 insmodrmmod(基础方法)

这对工具提供了更底层的控制,但需要手动处理依赖关系。

4.1 加载模块 (insmod)

1
2
# 必须指定模块的完整路径
sudo insmod /lib/modules/$(uname -r)/kernel/drivers/block/floppy.ko

关键限制:如果 floppy.ko 依赖其他模块(如特定总线驱动),insmod 会直接失败并报错,而不会自动加载依赖项。

4.2 卸载模块 (rmmod)

1
2
# 使用模块名(不含.ko后缀和路径)
sudo rmmod floppy

重要:只能卸载当前未被使用且没有其他模块依赖的模块。

4.3 insmod 常用参数

参数 功能
-f 强制加载,忽略内核版本检查(危险)。
-k 将模块标记为“自动卸载”。
-o <名称> 指定加载后模块的名称(可不同于文件名)。
-p 仅测试模块是否能加载,不实际加载。
-s 将操作信息写入系统日志。
-v 显示详细信息。

示例:强制加载并输出详细信息

1
sudo insmod -f -v /path/to/module.ko

五、模块状态查看与系统集成

5.1 查看已加载模块

1
2
3
4
5
# 查看所有已加载模块
lsmod

# 配合grep过滤
lsmod | grep vfat

输出格式

1
2
3
Module                  Size  Used by
vfat 24576 0
fat 73728 1 vfat
  • Module:模块名称。
  • Size:模块占用的内存大小(字节)。
  • Used by:被哪些模块或进程使用(数字表示引用计数)。

5.2 模块配置文件

模块的别名、黑名单等配置位于:

  • /etc/modprobe.d/ 目录下的 .conf 文件
  • /etc/modules-load.d/ 目录(定义启动时自动加载的模块)

示例:创建文件 /etc/modprobe.d/blacklist.conf 可禁用特定模块

1
2
# 禁用有问题的无线网卡驱动
blacklist acer_wmi

5.3 开机自动加载模块

方法一:编辑 /etc/modules 文件(传统方法)

1
2
3
4
sudo nano /etc/modules
# 添加模块名,每行一个
vfat
nvidia

方法二:使用 modules-load.d 目录(现代方法)

1
2
3
# 创建配置文件
echo "vfat" | sudo tee /etc/modules-load.d/vfat.conf
echo "nvidia" | sudo tee /etc/modules-load.d/nvidia.conf

六、故障排除与最佳实践

6.1 常见错误与解决

  • 错误:insmod: ERROR: could not insert module: Invalid module format
    原因:模块编译时的内核版本与当前运行内核不匹配。
    解决:重新编译模块或寻找对应版本的模块。

  • 错误:modprobe: FATAL: Module xxx not found
    原因:模块未安装或不在标准搜索路径。
    解决

    1. 检查模块是否存在:find /lib/modules -name "*.ko" | grep xxx
    2. 运行 sudo depmod -a 更新数据库。
  • 错误:rmmod: ERROR: Module xxx is in use
    原因:模块正在被进程或其他模块使用。
    解决:先停止相关进程,或使用 modprobe -r 尝试智能卸载。

6.2 依赖关系解析示例

假设模块 A.ko 依赖于 B.ko

1
2
3
4
5
6
7
8
9
# 使用 insmod 会失败
sudo insmod /path/to/A.ko # 失败:未加载 B.ko

# 需要先加载依赖
sudo insmod /path/to/B.ko
sudo insmod /path/to/A.ko # 成功

# 使用 modprobe 自动处理
sudo modprobe A # 自动先加载 B.ko,再加载 A.ko

6.3 最佳实践总结

  1. **日常操作首选 modprobe**:让系统自动处理复杂的依赖关系。
  2. **调试时使用 insmod/rmmod**:当需要精确控制加载顺序或排查依赖问题时。
  3. 始终更新依赖数据库:安装新内核或模块后,运行 sudo depmod -a
  4. 检查模块使用情况:卸载前使用 lsmod | grep <模块名> 查看引用计数。
  5. 利用配置目录:将自定义设置放在 /etc/modprobe.d/ 中,便于管理。

七、总结对比

操作 modprobe 方式 insmod/rmmod 方式
加载模块 sudo modprobe <模块名> sudo insmod <完整路径>
卸载模块 sudo modprobe -r <模块名> sudo rmmod <模块名>
依赖处理 自动,读取 modules.dep 手动,需按顺序加载
模块查找 搜索标准目录(/lib/modules/ 需提供完整路径
适用场景 生产环境、日常管理 开发调试、低级操作

最终建议:对于大多数用户和管理员,modprobe 是更安全、便捷的选择。只有在深入了解模块依赖关系,或进行系统级调试时,才需要使用 insmodrmmod 这对底层工具。