0

0

Linux如何调试内核模块崩溃_Linuxdmesg与符号表分析

尊渡假赌尊渡假赌尊渡假赌

尊渡假赌尊渡假赌尊渡假赌

发布时间:2025-11-25 21:10:02

|

385人浏览过

|

来源于php中文网

原创

答案是dmesg和符号解析为内核模块调试核心。系统崩溃时,dmesg输出Oops等错误及PC寄存器地址;结合带-g调试信息编译的.ko文件与addr2line或gdb工具,可将地址还原为源码行号,定位问题。

linux如何调试内核模块崩溃_linuxdmesg与符号表分析

当Linux内核模块发生崩溃时,系统通常不会像用户程序那样给出明确的错误提示。调试这类问题的关键在于理解内核日志输出和符号解析机制。dmesg是获取内核打印信息的核心工具,而符号表则是将内存地址还原为函数名、变量名的基础。掌握这两者结合使用的方法,能有效定位模块崩溃原因。

dmesg查看内核崩溃信息

内核模块出错后,第一条线索往往来自dmesg输出。系统在发生Oops或panic时会自动打印寄存器状态、调用和出错地址。

运行以下命令查看最近的内核消息:

dmesg | tail -20

重点关注包含“Oops”、“BUG”、“WARNING:”或“Unable to handle kernel paging request”的行。例如:

[ 1234.567890] Unable to handle kernel paging request at virtual address ffffff00 [ 1234.567891] pgd = c0004000 [ 1234.567892] *pgd=00000000 [ 1234.567893] Internal error: Oops: 17 [#1] PREEMPT SMP ARM [ 1234.567894] Modules linked in: mymodule(+) [ 1234.567895] CPU: 0 PID: 123 Comm: insmod Not tainted 5.15.0-rc1+ #1 [ 1234.567896] Hardware name: Generic DT based system [ 1234.567897] PC is at mymodule_do_something+0x24/0x100 [mymodule] [ 1234.567898] LR is at init_module+0x18/0x1000 [mymodule]

这里的PC(程序计数器)指向了崩溃位置:mymodule_do_something+0x24,说明问题出现在该函数偏移0x24字节处。

确保模块编译包含调试符号

要将地址转换为源码级别的函数名,必须保证模块编译时启用了调试信息。Makefile中应包含以下选项:

  • GCC编译参数加入 -g 以生成调试信息
  • 避免 strip 模块文件
  • 保留 .ko 文件与运行环境一致

典型的模块Makefile示例:

obj-m += mymodule.o CFLAGS_mymodule.o := -g -O2 KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules

编译完成后,.ko文件中会包含足够的ELF调试信息,供后续分析使用。

使用addr2line或gdb解析崩溃地址

有了带符号的.ko文件和崩溃地址,就可以进行反向定位。假设Oops中显示PC位于 mymodule_do_something+0x24,先提取函数起始地址。

通过readelf获取函数虚拟地址:

readelf -s mymodule.ko | grep mymodule_do_something

输出可能为:

社研通
社研通

文科研究生的学术加速器

下载
55: c0000120 64 FUNC GLOBAL DEFAULT 1 mymodule_do_something

函数起始地址为c0000120,偏移0x24对应的实际地址是 c0000120 + 0x24 = c0000144。

使用addr2line查找源码位置:

addr2line -e mymodule.ko 0xc0000144

输出类似:

/home/dev/mymodule/main.c:45

这表示崩溃发生在main.c第45行。也可以用gdb加载模块进行更深入分析:

gdb mymodule.ko (gdb) list *mymodule_do_something+0x24

处理未导出符号或内核自身崩溃

如果崩溃涉及内核函数而非模块本身,需使用vmlinux镜像配合分析。vmlinux是带符号的内核镜像,通常位于/boot或内核源码目录下。

使用相同方法解析内核地址:

addr2line -e /usr/src/linux/vmlinux 0xc0123456

注意:某些发行版提供分开的debuginfo包(如kernel-debuginfo),需单独安装才能获得vmlinux。

另外,可借助scripts/decode_stacktrace.sh脚本(存在于内核源码中)自动完成符号翻译:

dmesg | tail -20 > oops.txt ./scripts/decode_stacktrace.sh oops.txt vmlinux

基本上就这些。关键点在于保留完整的调试符号、准确匹配运行中的模块版本,并熟练使用dmesg与地址解析工具组合排查问题。虽然过程看似繁琐,但一旦掌握,内核模块调试效率会显著提升。

相关专题

更多
scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

187

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

271

2023.10.25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

386

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

569

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

386

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

569

2023.08.10

default gateway怎么配置
default gateway怎么配置

配置default gateway的步骤:1、了解网络环境;2、获取路由器IP地址;3、登录路由器管理界面;4、找到并配置WAN口设置;5、配置默认网关;6、保存设置并退出;7、检查网络连接是否正常。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.12.07

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1347

2023.06.21

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.6万人学习

php初学者入门课程
php初学者入门课程

共10课时 | 0.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号