linux_kernel调试手段
本文系统梳理几种常见且实用的 Linux Kernel 调试手段,涵盖崩溃分析、函数级追踪、动态调试以及性能分析工具。每种工具都适用于不同的问题场景,合理组合使用往往能事半功倍。
1. crash
1.1 简介
概述: crash是一个强大的linux内核调试工具,主要用于分析系统运行时状态活在内核崩溃后分析生成的内存转储文件。结合了传统unix crash命令的内核特定功能与gnu gdb调试的源代码级调试能力,提供了一个交互式调试环境
主要功能:
- 分析运行中的系统状态
- 在系统崩溃后,通过分析内存转储文件(如vmcore)进行故障诊断,支持
kdump、netdump、diskdump等多种转储机制生成的内存转储文件 - 检查内核数据结构、线程、模块、内存使用情况等
1.2 快速上手
1. 查看kexec是否安装:
1 | |
kdump依赖kexec机制加载 dump-capture kernel。
2. 安装依赖:
1 | |
3. 查看dump-capture kernel是否加载到内存中:
1 | |
4. 获取内核映像文件(vmlinux):
1 | |
5. 提供转储文件:
一般来说kernel panic后就会生成vmcore
1 | |
6. 系统重启后vmcore在/var/crash/<日期>/下
7. 运行crash:
1 | |
其实可以直接分析运行时内核core,文件路径为/proc/kcore
2. ftrace
2.1 简介
概述:
基于函数插桩,在内核编译时,若启用了CONFIG_FUNCTION_TRACER选项,编译器会在每个函数入口处插入调用mcount的指令。运行时,ftrace可以动态地将这些指令替换为跳转到跟踪处理函数的指令,从而实现对函数调用的追踪
使用动态插桩技术:
- 编译时,记录所有可被追踪的函数
- 运行时,将函数入口的
mcount调用替换为nop(无操作)指令 - 当启用追踪某个函数时,再将对应的
nop指令替换为跳转指令,实现动态启用和禁用追踪功能
2.2 快速上手
1. 设置trace类型,我常用的是function类型,查看某个函数是否被调用到:
1 | |
2. 设置函数过滤器,追踪指定kernel函数:
1 | |
3. 启用追踪:
1 | |
4. 查看输出:
1 | |
3. pr_debug()
pr_debug()是内核中用于调试日志输出的宏,相比直接使用printk,它可以通过 dynamic debug 机制动态开启或关闭。
1. kernel需要开启编译配置:
1 | |
2.
查看所有kernel使用pr_debug()的地方:
1 | |
3. 开启某个文件的所有调试信息:
1 | |
4. 开启特定函数的调试信息:
1 | |
5. 开启特定行的调试信息:
1 | |
6. 开启某个模块的调试信息:
1 | |
7. 查看日志:
1 | |
4. perf
4.1 简介
概述: 用于系统性能调优,瓶颈定位和应用程序行为分析。利用硬件性能计数器(PMU)、软件事件、tracpoints、kprobes和uprobes等机制,提供对内核和用户空间的深入观察能力
事件类型:
- 硬件事件:cpu周期数、缓存命中/未命中、分支预测等
- 软件事件:如上下文切换、页面错误等
- tracepoints:内核中预定义的追踪点
- kprobes/uprobes:动态插桩机制,用于内核空间和用户空间的函数追踪
子命令:
- stat:收集并显示性能计数器统计信息
- record:采样并记录性能数据
- report:分析
record命令生成的数据文件 - top:实时显示系统中消耗最多cpu的函数
- annotate:显示源代码或汇编代码中的热点
- sched:分析调度器行为和延迟
- list:列出可用的事件类型
4.2 生成火焰图
在实际排查性能问题时,我最常用的是配合 FlameGraph 生成火焰图,用于观察函数调用栈的整体开销分布。
1. 火焰图生成脚本下载: https://github.com/brendangregg/FlameGraph
2. 执行perf record子命令采样数据:
1 | |
3. 生成火焰图:
1 | |
打开
flame.svg即可查看。