Linux内核模块管理:lsmod命令详解与实战应用
1. 项目概述从“黑盒”到“白盒”lsmod是你的系统模块探照灯如果你在Linux世界里待过一阵子尤其是折腾过驱动、内核或者排查过一些稀奇古怪的系统问题那你大概率听说过或者用过lsmod这个命令。乍一看它的名字平平无奇——“list modules”列出模块。很多新手可能会觉得这不就是个简单的列表命令吗看一眼就完事了。但在我十多年的运维和开发经历里lsmod远不止是一个“查看”工具它更像是一把打开Linux内核运行时状态的钥匙一个系统稳定性的“听诊器”。简单来说lsmod命令用于显示当前Linux内核已经加载的所有模块也叫内核模块的信息。内核模块是什么你可以把它想象成乐高积木。完整的Linux内核是一个庞大而复杂的系统如果所有功能都编译进内核它会变得无比臃肿启动慢占用内存多。模块化设计允许内核在保持一个精简核心vmlinuz的同时将许多功能比如硬件驱动、文件系统支持、网络协议等设计成独立的、可动态加载和卸载的“积木块”。当你插入一个U盘内核会自动加载usb-storage模块当你挂载一个NTFS格式的硬盘可能需要手动加载ntfs模块。lsmod就是告诉你此时此刻你的系统内核上到底插着哪些“乐高积木”它们之间又是如何相互依赖、层层堆叠的。这个命令解决的核心问题是“系统透明化”。在没有图形化工具或深入内核源码的情况下它提供了最直接、最快速的途径让你了解系统底层正在运行什么额外的代码。这对于驱动调试某个硬件不工作是不是对应的驱动模块没加载、故障排查系统突然变慢是不是某个模块内存泄漏、安全审计是否有可疑的内核模块被植入以及单纯的学习理解系统构成都有着不可替代的价值。无论你是系统管理员、运维工程师、嵌入式开发者还是对Linux底层充满好奇的极客掌握lsmod及其背后的知识都是你从“用户”迈向“掌控者”的关键一步。2. 命令输出详解读懂三列数据背后的故事直接输入lsmod并回车你会看到类似下面的输出Module Size Used by usb_storage 73728 0 uas 28672 0 hid_generic 16384 0 joydev 24576 0 i915 1871872 3 drm_kms_helper 184320 1 i915 drm 491520 4 i915,drm_kms_helper video 45056 1 i915这个输出清晰、简洁但每一列都蕴含着重要信息。我们一列一列拆开看理解它们到底在说什么。2.1 第一列Module模块名称这一列最简单就是内核模块的名称。这个名字通常对应着/lib/modules/$(uname -r)/目录下的一个.koKernel Object文件。例如usb_storage模块对应的文件很可能是/lib/modules/5.15.0-91-generic/kernel/drivers/usb/storage/usb-storage.ko。注意模块名中的下划线_和连字符-有时会让人困惑。在模块名中通常使用下划线如usb_storage但在对应的文件名中可能使用连字符如usb-storage.ko。这取决于内核源码中的命名规范lsmod显示的是模块的内部名称。2.2 第二列Size模块大小这一列显示的是模块被加载到内核后所占用的内存大小单位是字节。例如i915模块的1871872表示它大约占用了1.8MB的内存。这个大小包含了模块的代码段text、数据段data等。这个数字非常实用评估内存占用如果你在为一个内存受限的嵌入式设备优化系统可以通过lsmod快速查看哪些模块是“内存大户”考虑是否有更轻量级的替代方案或者是否可以编译进内核而非以模块形式存在编译进内核可能在某些方面更高效但失去了动态加载的灵活性。排查异常如果一个模块的大小看起来异常巨大与你认知中的同类驱动不符这可能是一个警示信号需要进一步检查该模块的版本或来源。2.3 第三列Used by被引用计数与依赖关系这是lsmod输出中最富含信息量也最容易误解的一列。它的格式是“数字 [依赖模块列表]”。数字引用计数这个数字表示当前有多少个“东西”正在使用这个模块。这个“东西”可以是其他内核模块。正在使用该模块所提供功能的活跃进程。内核本身如果模块被编译为内置即y而非模块m则此计数通常为 -1 或一个固定值但lsmod不显示内置部分。最关键的一点只有当这个数字变为0时你才能使用rmmod命令安全地卸载该模块。如果数字大于0强行卸载会导致使用该模块的功能失效甚至可能引起内核恐慌Kernel Panic。方括号内的依赖模块列表这部分列出了依赖于当前模块的其他模块。注意是“谁依赖我”而不是“我依赖谁”。这是一个反向依赖关系。让我们用上面的例子解析i915 1871872 3i915模块Intel集成显卡驱动被3个“东西”使用着后面没跟方括号意味着目前没有其他模块依赖它但可能有进程在使用它。drm_kms_helper 184320 1 i915drm_kms_helper模块被1个“东西”使用并且依赖于它的模块是i915。这很合理Intel显卡驱动需要DRM/KMS辅助模块的功能。drm 491520 4 i915,drm_kms_helperdrm模块被4个“东西”使用依赖于它的模块有i915和drm_kms_helper。这揭示了依赖链i915-drm_kms_helper-drm。i915依赖drm_kms_helper而drm_kms_helper又依赖drm。理解这种反向依赖关系对于模块管理至关重要。如果你想卸载drm模块你必须先卸载所有依赖它的模块i915和drm_kms_helper并且要按依赖顺序反向操作。这就是为什么我们通常使用modprobe -r来卸载模块因为它会自动处理依赖关系而rmmod需要手动按序操作。3. 核心操作与进阶技巧不止于查看掌握了如何阅读lsmod的输出我们就可以进行一些实际操作了。lsmod本身只是一个查看工具但它通常与模块管理的其他命令协同工作。3.1 基础查看与信息过滤单纯的lsmod会列出所有模块。当模块很多时我们可以结合其他命令行工具进行过滤。查找特定模块最常用的方法是使用grep。lsmod | grep usb这会列出所有模块名中包含“usb”的模块例如usb_storage,usbhid,xhci_hcd等。按大小排序有时我们关心哪些模块占用内存最多。lsmod | sort -k2 -nr | head -20这个命令组合做了以下几件事lsmod输出列表。sort -k2 -nr以第二列Size为键进行排序-n表示按数值排序-r表示逆序从大到小。head -20只显示前20行。 这样你就能快速定位到系统中的“内存消耗大户”。3.2 结合modinfo获取模块详情lsmod告诉你模块是否加载以及粗略情况而modinfo命令则可以展示模块的详细信息。两者结合才能对模块有完整认识。modinfo i915输出会包含filename模块文件的实际路径。description模块功能的文本描述。author作者。license许可证如GPL这对于商业发行版合规性很重要。depends该模块所依赖的其他模块列表。这是正向依赖关系与lsmod的“Used by”形成互补。例如modinfo i915可能会显示depends: drm,drm_kms_helper,video这意味着加载i915前这些模块必须就位。vermagic一个特殊的字符串包含内核版本、编译器版本等用于确保模块与当前运行的内核兼容。如果vermagic不匹配模块将无法加载。一个典型的工作流是用lsmod | grep xxx找到模块 - 用modinfo xxx查看其详细信息特别是依赖关系和描述。3.3 模块的加载与卸载实战虽然lsmod不负责加载卸载但它是操作前后的必要检查手段。加载模块使用modprobe。它是智能的会读取模块的依赖信息depends并按需自动加载依赖模块。sudo modprobe v4l2loopback执行后立刻运行lsmod | grep v4l2loopback你应该能看到它已被加载并且其依赖的模块如果有也会被一并列出。卸载模块同样推荐使用modprobe -r。sudo modprobe -r v4l2loopback执行后再运行lsmod | grep v4l2loopback它应该消失了。modprobe -r会尝试递归卸载目标模块及其不再被使用的依赖模块。手动卸载高级使用rmmod。这需要你手动处理依赖即必须从依赖链的末端开始卸载且确保引用计数为0。# 假设我们想手动卸载 drm 模块但 lsmod 显示 # i915 依赖于 drm_kms_helper # drm_kms_helper 依赖于 drm # 那么顺序必须是 sudo rmmod i915 # 先卸载最末端的 sudo rmmod drm_kms_helper # 再卸载中间层 sudo rmmod drm # 最后卸载核心模块警告像i915这种关键图形驱动卸载它会导致图形界面崩溃如果正在使用。这只是一个理论示例切勿在生产环境或桌面环境中随意尝试。实操心得绝大多数情况下请永远使用modprobe和modprobe -r来加载和卸载模块。insmod和rmmod是更底层的工具只在你明确知道自己在做什么并且需要绕过依赖检查或处理特殊模块时才使用。modprobe是安全且省心的首选。4. 高级应用与深度排查场景lsmod的价值在高级应用和问题排查中体现得淋漓尽致。它不仅仅是“看看有什么”更是分析系统行为、定位疑难杂症的起点。4.1 排查硬件驱动问题这是lsmod最经典的应用场景之一。当你插入一个新硬件比如USB无线网卡没反应时首先lsmod查看是否有相关的驱动模块被加载。例如对于一款常见的rtl8192cu芯片USB网卡你可以运行lsmod | grep rtl或lsmod | grep 8192。解读结果如果找到了如rtl8192cu并且Used by计数不为0说明驱动已加载。问题可能出在配置网络管理器、固件缺失或硬件本身故障。你可以进一步用dmesg | grep rtl查看内核日志看驱动初始化时有没有报错如“firmware not found”。如果没找到说明内核没有自动加载对应驱动。可能的原因有驱动未安装系统内核不包含该模块。你需要检查/lib/modules/$(uname -r)/kernel/drivers/...下是否存在对应的.ko文件或者是否需要从DKMS或源码编译安装。驱动存在但未自动加载硬件可能没有触发udev规则自动加载模块。你可以尝试手动sudo modprobe rtl8192cu来加载如果成功则可以通过将模块名添加到/etc/modules-load.d/下的配置文件中来实现开机自动加载。4.2 分析系统性能与资源占用一个模块被加载后它的代码就在内核空间运行。一个有bug的模块可能会导致内存泄漏、CPU占用高或系统不稳定。内存泄漏嫌疑如果你怀疑某个模块有内存泄漏可以监控其Size列是否在持续、异常地增长虽然这并不常见因为模块大小通常是静态的。更常见的做法是结合dmesg和journalctl查看内核日志中是否有该模块相关的OOM内存不足或错误信息。CPU/IO问题如果一个内核线程可以通过ps aux | grep \[kworker\]查看持续占用高CPU并且其名称与某个模块相关lsmod可以帮你确认该模块是否存在。例如一个名为[kworker/u16:3-e1000e]的线程指向e1000eIntel千兆网卡驱动模块这可能意味着该驱动正在处理大量的网络数据或遇到了问题。4.3 安全审计与可疑模块检测在安全领域lsmod是检查是否有未知或恶意内核模块被加载的基本手段。内核模块拥有极高的权限一个恶意模块rootkit可以隐藏进程、文件监听网络危害极大。建立基准在系统干净、可信的状态下保存一份lsmod的输出。lsmod ~/trusted_lsmod_snapshot.txt定期比对当怀疑系统安全时再次运行lsmod与基准快照进行对比。lsmod ~/current_lsmod.txt diff ~/trusted_lsmod_snapshot.txt ~/current_lsmod.txt分析差异重点关注新增的、你不认识的模块。模块名称看起来是随机字符串或试图伪装成合法模块如drm和drm_x。结合modinfo 可疑模块名查看其描述、作者和签名如果有。合法的内核模块通常有明确的描述和GPL等开源许可证。深入检查对于可疑模块找到其文件路径通过modinfo或直接在/lib/modules/下搜索检查文件哈希、修改时间并考虑使用rmmod卸载如果引用计数为0或使用专业rootkit检测工具如rkhunter,chkrootkit进行扫描。注意事项这种方法对于简单的、不隐藏自身的rootkit有效。但高级的rootkit会挂钩系统调用使自己从lsmod、modinfo甚至文件列表中“消失”。因此lsmod是安全检查的必要非充分条件需要结合其他离线检测、完整性校验等手段。4.4 理解系统启动与服务依赖许多系统服务在启动时依赖于特定的内核模块。例如Docker服务需要overlayfs或aufs等存储驱动模块某些文件系统监控工具如inotify的增强需要加载fanotify模块。通过lsmod你可以验证这些前提条件是否满足。在调试一个启动失败的服务时查看其日志如果日志提到“Module xxx not found”或“Function not implemented”下一步就是去用lsmod检查对应模块是否已加载。5. 常见问题与疑难解答实录在实际使用中你肯定会遇到各种各样的问题。下面是我总结的一些典型场景和解决方法。5.1 模块加载失败原因分析与解决步骤当你执行sudo modprobe some_module失败时别慌按以下步骤排查检查模块是否存在find /lib/modules/$(uname -r) -name *some_module*.ko如果找不到说明你的当前内核没有编译这个模块。你可能需要安装包含该模块的Linux内核头文件或额外模块包如linux-modules-extra-$(uname -r)。或者自己编译内核并启用该模块。检查模块依赖modinfo some_module | grep depends确保所有依赖的模块都已加载。你可以尝试手动加载依赖项或者直接使用modprobe它会自动处理依赖。查看内核日志这是获取失败原因最直接的途径。sudo dmesg | tail -20 # 或者使用 systemd 的系统 sudo journalctl -k --since1 minute ago日志中通常会包含具体的错误信息例如Required key not available模块签名验证失败可能与安全启动Secure Boot有关。可以尝试禁用安全启动或给模块签名。Invalid module format/version magic不匹配模块是为其他内核版本编译的。你需要找到或编译与当前内核版本完全匹配的模块。Unknown symbol模块依赖的某个内核符号函数或变量不存在。这通常发生在模块版本不兼容或者你尝试加载一个依赖其他未加载模块的模块时。检查黑名单模块可能被列入黑名单阻止其加载。grep -r some_module /etc/modprobe.d/黑名单文件通常以.conf结尾里面用blacklist some_module语句来禁止加载。5.2 模块卸载失败引用计数不为0的困境这是最常遇到的问题。你想卸载模块A但rmmod A提示Module A is in use。第一步看lsmod。lsmod | grep ^A查看Used by计数是多少以及方括号里列出了哪些依赖模块。第二步找出谁在使用。如果Used by列有依赖模块方括号内有内容如B, C那么你必须先卸载B和C。如果没有列出依赖模块但计数仍大于0说明可能有进程在使用它。查找使用特定模块的进程比较困难没有直接命令。但你可以使用lsof或fuser检查是否有进程打开了该模块相关的设备文件通常在/dev/下。但这需要你知道模块创建了哪些设备节点。最实用的方法重启相关服务或进程。例如如果你卸载一个网络驱动失败尝试sudo systemctl stop NetworkManager或关闭所有网络连接后再试。如果是文件系统模块确保所有分区都已卸载。第三步强制卸载危险。这是最后的手段可能导致系统不稳定或崩溃。sudo rmmod -f A-f(force) 参数会强制卸载即使引用计数不为0。这可能导致正在使用该模块的进程崩溃或硬件处于不可控状态。仅在测试环境或你完全清楚后果时使用。5.3 lsmod输出为空或异常lsmod输出为空这几乎不可能发生在正常的运行系统中。如果发生可能意味着/proc/modules文件lsmod的数据源无法读取或者你处在一个极其精简的容器环境某些容器镜像为了极致精简可能不挂载/proc或内核模块功能被阉割。检查cat /proc/modules是否正常。模块大小显示为0有些非常古老的模块或特殊架构下的模块可能会显示为0但现代内核中很少见。如果看到可以忽略或查阅特定模块的文档。5.4 如何永久加载或禁用模块开机自动加载将模块名如v4l2loopback单独一行写入/etc/modules-load.d/*.conf文件中例如/etc/modules-load.d/my-modules.conf。系统启动时systemd-modules-load服务会读取这些文件并加载模块。永久禁用黑名单创建或编辑/etc/modprobe.d/blacklist.conf文件添加blacklist module_name。例如如果你不想系统自动加载有问题的nouveau开源NVIDIA驱动可以将其加入黑名单。黑名单不仅阻止自动加载modprobe命令也会忽略它。但请注意如果其他模块依赖它或者内核将其编译为内置y而非模块m黑名单是无效的。lsmod命令就像Linux内核世界的一个实时仪表盘简洁但信息密度极高。从简单的驱动检查到复杂的安全审计从性能问题定位到系统启动依赖验证它的身影无处不在。掌握它意味着你拥有了透视系统底层运行状态的能力。我个人的习惯是在接手任何一台新的Linux服务器或遇到任何底层异常时lsmod总是我敲下的第一批诊断命令之一。它给出的答案往往能直接指引下一步的排查方向。花点时间熟悉你的lsmod输出了解每个常驻模块的作用这会在未来某个棘手的时刻为你节省大量盲目搜索的时间。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2622646.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!