明白了,我给你整理一份 “Linux 卸载驱动模块导致内核崩溃的排查与调试实践记录”,包括操作步骤、常见问题、调试工具和排查思路,适合做笔记或技术记录。


Linux 驱动模块卸载导致内核崩溃 — 排查调试记录

一、问题背景

在 Linux 系统中,有时需要卸载内核模块(Driver Module)进行更新或调试,例如:

sudo modprobe -r my_driver
# 或
sudo rmmod my_driver

在执行时,系统可能出现:

  • 内核 oops / panic
  • 系统卡死或重启
  • dmesg 出现 BUG: unable to handle kernel NULL pointer

目的:分析内核崩溃原因并排查解决。


二、前期准备

  1. 安装调试工具
sudo apt install linux-tools-$(uname -r) linux-headers-$(uname -r) gdb crash

  1. 开启内核日志持久化
sudo dmesg -n 7   # 将所有日志打印到控制台
sudo journalctl -f

  1. 保留内核 panic 日志
  • 如果崩溃导致重启,可以开启 kdump:
sudo apt install kdump-tools
sudo systemctl enable kdump
sudo systemctl start kdump

  • 配置 /etc/kdump.conf,保存 crash dump。

三、卸载模块的安全流程

1. 查看模块依赖

lsmod | grep my_driver
modinfo my_driver

确认模块没有被其他模块依赖,否则卸载会失败或导致依赖模块崩溃。

2. 停用使用该模块的资源

  • 关闭使用设备的应用程序
  • 卸载文件系统 / 断开网卡 / 停止硬件操作

3. 卸载模块

sudo modprobe -r my_driver

避免直接 rmmod 可能引发依赖问题。


四、出现崩溃后的排查

1. 查看内核日志

dmesg | tail -50
journalctl -k -n 100

常见信息:

  • NULL pointer dereference
  • use-after-free / memory corruption
  • driver BUG 触发 oops

2. 收集内核 oops 信息

sudo cat /var/log/kern.log | grep -i my_driver

  • 记录函数调用栈、错误地址
  • 注意 Call Trace 部分,是关键线索

3. 使用 crash 工具分析 dump

假设已配置 kdump 并生成 vmcore:

sudo crash /usr/lib/debug/boot/vmlinux-$(uname -r) /var/crash/2025-10-13/vmcore

在 crash shell 内:

bt          # 查看堆栈回溯
ps          # 查看进程状态
mod          # 查看模块信息

分析崩溃是由于模块未正确释放资源,还是内核 bug。


五、调试与解决策略

问题类型解决策略
模块仍被使用确认设备关闭 / 依赖模块卸载
内存释放错误检查 module_exit() 是否正确释放所有内核资源(task, memory, irq)
内核访问 NULL / 野指针查看模块源码,确认 exit 函数中没有访问已释放结构体
多线程 / IRQ 相关禁用中断或停止 worker thread 后再卸载模块

建议做法

  1. 添加调试日志:
printk(KERN_INFO "my_driver: exiting module\n");

  1. 使用 CONFIG_DEBUG_KERNEL / CONFIG_DEBUG_KMEMLEAK 编译内核,检查内存泄漏。
  2. 模拟卸载流程:
    • 关闭所有设备使用
    • 停止 kernel thread / worker thread
    • 再执行 modprobe -r

六、最佳实践

  1. 避免直接 rmmod,推荐 modprobe -r,自动处理依赖。
  2. 内核线程先 stop,再 free memory,避免野指针访问。
  3. 多线程驱动使用锁(spinlock / mutex)防止卸载时竞态。
  4. 测试环境先模拟,避免生产环境 panic。
  5. 开启内核 crash dump,方便分析 post-mortem。

七、记录示例(调试笔记模板)

时间: 2025-10-13 14:32
操作: modprobe -r my_driver
现象: 系统 panic, call trace:
[ 1234.567890] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
[ 1234.567895] CPU: 2 PID: 567 Tainted: G
[ 1234.567899] Call Trace:
[ 1234.567901]  my_driver_exit+0x34/0x50 [my_driver]
...
分析: module_exit() 中访问了已释放内存
解决: 修复 exit 函数,先 stop worker,再释放资源