在Linux系统内核模块的管理与故障排查中,lsmod与modinfo是两个核心但侧重点迥异的命令。许多用户虽然熟悉它们,却常困惑于两者信息不一致或无法定位问题。这恰恰是因为它们分别揭示了模块状态的不同维度:一个关注运行态,一个关注静态元数据。只有协同使用,才能构建完整的诊断视图。
lsmod仅显示模块加载状态,无法确认其实际功能状态;modinfo仅读取磁盘模块文件的元数据信息。二者必须配合使用:lsmod用于检查运行状态,modinfo用于核查模块兼容性与配置参数。

简而言之,lsmod命令回答的是“哪些模块当前被加载到了系统内存中”,但它无法判断这些模块是否正在有效工作。而modinfo命令则完全不关心模块的运行状态,它的职责是解析存储在磁盘上的内核模块文件(.ko文件)内嵌的“说明文档”。因此,要全面掌握内核模块的状况,必须将这两个工具结合使用。
lsmod 输出中 Used by 列为 0 的含义与常见场景
当lsmod输出中Used by列显示为0时,切勿简单将其等同于“模块闲置可卸载”。它仅表示当前没有其他内核模块或子系统显式声明依赖于此模块,但该模块本身仍驻留在内存中。以下几种是典型情况:
- 条件未触发:模块已被
modprobe加载,但使其工作的条件尚未满足。例如,USB存储驱动usb_storage已加载,但对应的U盘设备尚未插入。 - 设备热移除:驱动对应的硬件被热拔插或断电。拔掉U盘后,
usb_storage模块可能仍在列表中,但Used by计数归零。 - 常驻监听型模块:如虚拟化模块
kvm_intel,即使当前没有虚拟机运行,它也会保持加载状态以准备接收指令,此时Used by长期为0属正常现象。 - 关键陷阱:
Used by 0绝不意味着模块可以安全卸载。尝试rmmod时,很可能仍会收到“Module is in use”错误。这是因为内核可能通过try_module_get()等内部机制持有引用,而lsmod的统计无法捕捉这类隐式依赖。
modinfo 查不到模块?先确认模块文件是否存在
当执行modinfo命令报错“ERROR: Module
- 确认内核版本:使用
uname -r获取当前运行的内核版本,例如6.8.0-45-generic。 - 查找模块文件:前往对应内核模块目录查找,例如:
ls /lib/modules/$(uname -r)/kernel/drivers/net/wireless/rtw88/rtw88_8822bu.ko*,确认.ko文件是否存在。 - 处理压缩模块:若模块文件为
.ko.xz等压缩格式,现代modinfo通常能直接识别。若旧版工具不支持,可临时解压验证:xz -d rtw88_8822bu.ko.xz。 - 区分模块名与文件名:注意模块名(加载时使用的名称)与文件名可能不同。例如文件
ath9k.ko对应模块名ath9k。而ath9k_common.ko通常是依赖模块,需通过modprobe ath9k加载主模块时自动引入,直接查询可能失败。
使用 grep 过滤 lsmod 输出时为何遗漏模块
试图用lsmod | grep nvidia来筛选所有NVIDIA相关模块?结果可能不完整,因为模块名未必包含你预设的关键词。常见原因如下:
- 模块名变体:NVIDIA驱动主模块为
nvidia,但其配套模块可能名为nvidia_uvm、nvidia_drm、nvidia_modeset。仅用grep nvidia会漏掉后者。 - 模块别名(Alias):某些模块通过
/etc/modprobe.d/下的配置文件设置了别名。例如btusb模块可能别名是bluetooth,此时用grep bluetooth搜索lsmod输出将一无所获。 - 大小写敏感:命令搜索是大小写敏感的。
lsmod | grep NVME无法匹配到全小写的nvme模块。 - 更可靠的过滤方法:建议使用
lsmod | awk '{print $1}' | grep -i 'nvidia\|nvme\|bt'。先通过awk精确提取第一列模块名,再进行不区分大小写(-i)的多关键词匹配。
modinfo -p 显示的参数,为何通过 modprobe 加载后未生效
modinfo -p列出的是模块在编译时预定义的、可供用户配置的参数列表。但这仅是“参数菜单”,要使参数实际生效,必须满足以下条件:
- 正确传递参数:必须在
modprobe命令中显式指定参数。例如:sudo modprobe r8169 disable_msi=1。 - 模块需重新加载:如果模块已加载在内存中,再次执行不带
-r选项的modprobe命令默认不会重新加载。必须先rmmod r8169卸载模块,再用带参数的modprobe命令重新加载。 - 内核启动参数:部分参数(尤其是驱动核心参数)必须在模块加载之前通过内核启动命令行传递。例如
i915.enable_psr=0,需写入GRUB配置的linux行中。系统启动后再通过modprobe设置是无效的。 - 验证参数生效:模块加载后,可检查
/sys/module/下对应的参数文件来验证:sudo cat /sys/module/r8169/parameters/disable_msi。若输出为Y或1,则表示参数已成功应用。
综上所述,Linux内核模块管理的复杂性并非源于命令本身,而在于其状态信息分散在三个不同的层次:运行时加载状态记录在/proc/modules(即lsmod的数据源);模块文件及其元数据存放在/lib/modules/$(uname -r)/目录下;而模块加载后的详细参数与实时状态则暴露在/sys/module/文件系统中。这三层信息各自独立,若只依赖单一工具查看,极易导致诊断方向偏差。掌握lsmod、modinfo及/sys文件系统的协同使用,是高效管理和排查内核模块问题的关键。
