暗色模式

Linux 内核模块管理:从 lsmod 到 modprobe 与黑名单配置

技术教程
2026-09-09
2
0
本文要点
  • 内核模块是按需加载进内核的功能单元(驱动、协议、文件系统等),Ubuntu 6.8 内核上可加载模块多达 6474 个,实际只加载了 122 个
  • lsmod 查看已加载模块与引用关系(Used by 列是依赖链),uname -r 确认内核版本
  • modinfo 查看模块元数据:(builtin) 表示编译进内核无法卸载,modinfo -p 列出可调模块参数
  • modprobe 加载时自动处理依赖(-n -v 干跑预览、--show-depends 看依赖树);卸载时 modprobe -r 会连同不再被使用的依赖一起卸载
  • 模块参数可通过 /sys/module/<名字>/parameters/ 在运行时查看
  • /etc/modprobe.d/*.conf 里的 blacklist 模块名 可阻止模块自动加载(系统自带的 blacklist 文件就是这么禁用不常用驱动)
  • 所有命令均在 Ubuntu 24.04(内核 6.8)上真实执行验证,截图即真实输出

什么是内核模块:按需加载的"内核插件"

Linux 内核不是把什么都编进去:网卡驱动、文件系统、网络协议这些功能,大部分被做成了可加载模块(loadable kernel module),平时躺在磁盘上,需要时由内核动态装进内存。这有点像"内核插件"——好处是内核本体可以很小,驱动坏了不用重编内核,升级驱动也只需换一个文件。

Ubuntu 24.04 的内核 6.8 上,这个对比非常直观:

uname -r
lsmod | wc -l
find /lib/modules/$(uname -r)/kernel -name '*.ko*' | wc -l

uname -r 告诉我们当前内核版本(6.8.0-136-generic);磁盘上的可加载模块文件有 6474 个(后缀 .ko.zst 是 zstd 压缩的模块二进制,模块目录名带版本号,一套内核一套模块);但此刻真正加载进内存的只有 122 个。剩下六千多个,都是"存在但不用"。

模块按功能分门别类存在 /lib/modules/$(uname -r)/kernel/ 下:net/ 放网络协议与驱动、fs/ 放文件系统、drivers/ 放硬件驱动、crypto/ 放加密算法。modules.dep 文件记录了模块间的依赖关系,modprobe 加载模块前会先读它。

lsmod:当前加载了哪些模块

lsmod(list modules)按行列出已加载模块的三个信息:名称、大小(字节)、Used by(被谁引用)

lsmod | head -12

查看内核版本与已加载模块

输出里几个值得注意的点:

  • 这台 demo 机启用了 NFS 服务,所以 nfsdnfsxfs 等文件系统模块都在列。
  • Used by 列就是依赖关系的实时快照nfs 577536 1 nfsv4 表示 nfs 模块正在被 nfsv4 引用;sunrpc 802816 20 nfsd,nfsv4,... 表示它被 20 处引用。这个数字为 0 的模块理论上可以被安全卸载。
  • 命令本身是 /proc/modules 的格式化输出,所以 lsmod | wc -l 得到 122(含表头一行,实际 121 个模块,本文按工具输出如实描述)。

modinfo:查看模块的"身份证"

要了解某个模块是干什么的、谁写的、能不能卸载,用 modinfo

modinfo ext4

modinfo 输出的是模块文件里的元数据:description 告诉你用途,author 是作者,alias 是模块支持的设备/功能别名(内核靠 alias 自动匹配加载模块),license 是许可证。特别注意 filename: (builtin) 这一行——builtin 表示 ext4 直接编译进了内核镜像,不是可加载模块。这类模块永远在运行、无法卸载、也没有对应的 .ko 文件,这是"能不能用 modprobe 管理它"的第一判断依据。

模块还经常带可调参数,modinfo -p(parameter)列出它们。拿防火墙常用的 xt_recent 模块举例:

modinfo -p xt_recent

xt_recent 用于按 IP 记录最近连接(fail2ban 的底层依赖之一),它暴露了 6 个参数:ip_list_tot(每个列表记住多少个 IP)、ip_list_perms/proc/net/xt_recent/* 文件的权限)、ip_list_uid/gid(文件属主)等——这些参数可以在加载时用 modprobe xt_recent ip_list_tot=200 指定,也可以在运行时通过 sysfs 调整(下文会演示)。

modinfo 查看模块元数据与参数

modprobe:加载与卸载,依赖自动处理

insmod(直接插入指定文件)不同,modprobe 是模块管理的正主——它只认模块名,会自动去模块目录里找文件、解析依赖并按顺序加载整棵依赖树

先用 -n(干跑,不真正加载)+ -v(显示细节)预览它会做什么:

modprobe -n -v 8021q

8021q 是 VLAN 网络协议模块(给网卡打 VLAN tag 用的)。干跑输出三行 insmod:除了 8021q.ko.zst 本身,还先加载了它的两个依赖 mrp.ko.zstgarp.ko.zst(分别是 MRP/ GARP 注册协议)。insmod 就要自己按顺序手动加载依赖,用 modprobe 全自动——这就是两者的核心区别。

想看完整的依赖树(含间接依赖),用 --show-depends

modprobe --show-depends 8021q

输出里多了 llc.ko.zststp.ko.zst——garp 又依赖 stpstp 依赖 llc,所以整条链是 llc → stp → garp → 8021q(另有 mrp 分支)。modprobe 加载时会按这个顺序依次插入。

真正加载并验证:

modprobe 8021q
lsmod | grep -E '8021q|garp|mrp'

grep 结果三行(另外两行 stpllc 是因为系统已有 bridge 模块在用它们,被一并列出):8021q 刚装上、Used by 0garp 20480 1 8021qmrp 20480 1 8021q 是刚被它带起来的依赖,各被引用 1 次。模块加载成功后,Used by 的引用关系全部就位。

卸载同样用 modprobe -r,它会先把不再被引用的依赖也一起卸掉

modprobe -r 8021q
echo "modprobe -r 退出码: $?"
lsmod | grep -E '8021q|garp|mrp' || echo "(依赖模块也已全部卸载)"

退出码 0 表示卸载成功,最后的 grep 查无结果,说明 8021q 连同 garpmrp 两个依赖一起被清干净了——这就是 modprobe -rrmmod(只能卸单个模块、依赖还挂着就报 busy)的区别。

加载、卸载模块与依赖自动清理

模块参数与 sysfs:运行时观察与调整

加载模块后,模块参数会在 /sys/module/<模块名>/parameters/ 下暴露成一个个文件。拿刚才提到的 xt_recent 实际验证:

modprobe xt_recent
ls /sys/module/xt_recent/parameters/
cat /sys/module/xt_recent/parameters/ip_list_tot
modprobe -r xt_recent

ls 列出 6 个参数文件(与 modinfo -p 一一对应),ip_list_tot 的当前值是 100——这就是该参数在这次加载中的生效值。参数文件通常是只读的(改它需要先卸载模块再带参数重载),但少数模块支持热改。这是运维排查时确认"模块到底用什么参数跑的"的最快途径,比翻文档可靠。

动手提示:加载模块前先 modprobe -n -v 干跑一遍,确认要加载的文件和依赖链;云服务器上改动网络相关模块(如 8021q、网卡驱动)前,确认不影响 SSH 连接。

黑名单:阻止模块自动加载

内核会按硬件 ID 自动匹配加载模块,但有些模块是"装上就出问题"的(比如老驱动和新硬件冲突、安全敏感的设备)。/etc/modprobe.d/ 目录下每个 .conf 文件一行一个配置,blacklist 模块名 就是禁用名单:

ls /etc/modprobe.d/
echo "blacklist pcspkr" > /etc/modprobe.d/blacklist-demo.conf
cat /etc/modprobe.d/blacklist-demo.conf

Ubuntu 云镜像自带的配置文件已经很有代表性:blacklist.confblacklist-framebuffer.conf(禁用旧帧缓冲驱动)、blacklist-rare-network.conf(禁用冷门网卡驱动避免误加载)……这些就是发行版默认的黑名单。自己加规则同理:新建 blacklist-xxx.conf 写一行 blacklist 模块名 即可,对已加载的模块不生效,只阻止自动加载——要立即生效还得先手动卸载它。

modprobe.d 里还常写两类配置:options 模块名 参数=值(固定加载参数,比命令行传递更持久)和 install/softdep(定制加载行为)。常见用法如 options iwlwifi disable_11ax=1 给网卡驱动固定参数,与 blacklist 同目录管理,重启后永久生效。

小结

内核模块管理四步走:

  1. uname -r 确认内核版本,lsmod 看已加载模块和引用关系,lsmod | wc -lfind /lib/modules/$(uname -r)/kernel -name '*.ko*' | wc -l 对比"装了但没用"的模块数量。
  2. modinfo 模块名 看元数据(builtin 的不能卸),modinfo -p 看可调参数。
  3. 装/卸modprobe 模块名 自动处理依赖,modprobe -n -v 先干跑,modprobe -r 连依赖一起清理。
  4. :参数看 /sys/module/<名>/parameters/,自动加载规则放 /etc/modprobe.d/blacklist 禁用、options 固定参数)。

云服务器上动内核模块的频率不高,但真遇到"网卡驱动加载失败""某个协议模块缺失"时,这套命令就是排查的起点。想了解内核层面相关的其他知识,可以配合《Ubuntu 内核升级与版本切换》理解模块与内核版本的对应关系,《Linux sysctl 内核参数调优》里的运行时参数与模块参数正好互补;模块加载失败时的 dmesg 日志排查方法,在《Linux 磁盘空间排查与清理》的 journald 部分有提到。

参考资料

发表评论

暂无评论,快来抢沙发吧!