内核调试trace的方法

本文介绍了一系列用于内核调试和性能分析的方法和技术,包括Ftrace和Perf工具的使用,以及如何通过命令查看中断、软中断等信息。

Ftrace目录

/sys/kernel/debug/tracing/events/timer/tick_stop/

使用filer过滤输出

TRACE代码目录

kernel-rt-3.10.0-thinkcloud/include/trace/events

Perf使用说明目录

kernel-rt-3.10.0-thinkcloud/tools/perf/Documentation

./perf list查看哪些event可以加入

 ./perf record -e sched:sched_switch -g -C 13-16 sleep 10

 ./perf report -g --no-children --stdio

其他内核调试命令

查看Local interrupt timer中断变化

watch -n1 -d "cat /proc/interrupts |egrep 'LOC|CPU'"

查看软中断

cat /proc/softirqs

查看任务及堆栈细节状态

echo 't' > /proc/sysrq-trigger

查看任务队列

cat /proc/sched_debug

查看每核定时器

cat /proc/timer_list

Ftrace目录

/sys/kernel/debug/tracing/events/timer/tick_stop/

使用filer过滤输出

Perf工具

perf已经放在180环境的node4上/root目录

./perf record -C 13,14,15,16

./perf report

<think> 我们刚刚讨论了`dump_stack()`的使用方法,现在用户的新需求是查找内核快速调试方法。根据用户提供的参考引用,我们可以总结出以下几种内核快速调试方法: 1. printk:最基础的调试方法,通过打印信息到内核日志 2. dump_stack:打印调用堆栈,用于追踪函数调用路径 3. OOPS消息分析:当内核发生致命错误时,会自动打印OOPS消息,其中包含寄存器状态和调用堆栈 4. kprobe:动态地在内核函数的特定位置插入断点,用于收集调试信息 5. ftrace内核内置的跟踪工具,可以跟踪函数调用、中断开关等事件 6. Systemtap:强大的脚本工具,可以动态地监控和跟踪运行中的内核 7. kgdb/kdb:内核级别的调试器,支持远程调试和单步执行 我们将重点介绍几种快速、无需复杂配置的方法(printk, dump_stack, OOPS分析, ftrace基础用法),因为用户强调“快速调试”。 ### 一、最快速调试方法:`printk` 与 `dump_stack` #### 1. **printk** - 内核日志输出 ```c // 在需要调试的位置插入 printk(KERN_DEBUG "debug: variable x=%d\n", x); ``` - **查看方式**:`dmesg` 或 `tail -f /var/log/kern.log` - **优先级**:从 `KERN_EMERG`(0) 到 `KERN_DEBUG`(7),通过 `/proc/sys/kernel/printk` 控制输出级别[^1] #### 2. **dump_stack** - 打印调用堆栈 ```c dump_stack(); // 直接插入代码中 ``` - **输出示例**: ```log [ 12.345678] Call Trace: [ 12.345679] [<ffffffff8107a04a>] dump_stack+0x46/0x58 [ 12.345681] [<ffffffff81234567>] my_debug_function+0x23/0x5a ``` - **作用**:立即输出当前函数调用链,无需崩溃触发[^1] ### 二、崩溃现场分析:OOPS 消息 当内核遇到无法处理的错误时(如空指针解引用),会打印 **OOPS 消息**,其中包含: - 错误类型(如“Unable to handle kernel NULL pointer dereference”) - 发生错误的CPU编号 - 寄存器状态 - 调用堆栈(与`dump_stack`类似) #### 分析步骤: 1. **定位出错指令地址**: ```log PC is at my_function+0x1a/0x30 ``` - `0x1a`:出错指令在函数内的偏移 - `0x30`:函数总长度 2. **反汇编定位代码行**: ```bash arm-linux-gnueabi-objdump -d vmlinux | grep -A 20 "my_function:" ``` 然后查找偏移量 `0x1a` 对应的指令[^3] ### 三、动态追踪:ftrace `ftrace` 是内核内置的低开销跟踪工具,无需重新编译内核。 #### 快速使用示例: 1. **启用函数跟踪**: ```bash cd /sys/kernel/debug/tracing echo function > current_tracer echo 1 > tracing_on # 执行待调试操作 echo 0 > tracing_on cat trace > /tmp/trace.log ``` 2. **只跟踪特定函数**: ```bash echo my_debug_function > set_ftrace_filter ``` 3. **输出解析**: ```log # tracer: function # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | myapp-1234 [001] 456.789012: my_debug_function <-caller_function ``` - 显示函数调用关系及时间戳[^1] ### 四、调试方法对比表 | 方法 | 使用场景 | 速度 | 复杂度 | 需重启 | |---------------|------------------------------|--------|--------|--------| | `printk` | 打印变量值、流程标志 | ★★★ | ★ | 需要 | | `dump_stack` | 函数调用路径追踪 | ★★★ | ★ | 需要 | | OOPS分析 | 崩溃现场分析 | ★★ | ★★ | 不需要 | | ftrace | 动态函数调用追踪 | ★★ | ★★ | 不需要 | | kprobe | 在任意函数插入断点收集数据 | ★ | ★★★ | 不需要 | > **注**:速度评级(★越多越快);复杂度评级(★越多越简单) ### 五、快速调试选择建议 1. **逻辑错误排查** → `printk` + `dump_stack` 2. **崩溃问题** → 分析自动生成的 OOPS 消息 3. **性能问题/并发竞争** → `ftrace` 或 `kprobe` §§相关问题§§ 1. 如何配置 `ftrace` 来跟踪内核模块中的函数? 2. 当系统因 `printk` 过多而变慢时,有哪些优化方法? 3. 如何利用 `kprobe` 实现内核函数的动态断点? [^1]: [Linux内核的经典调试方式](http://blog.youkuaiyun.com/itsenlin/article/details/43205983) [^2]: [linux内核调试方法](https://example.link2) [^3]: [内核调试的几种方法](https://example.link3) </think> ### 内核快速调试方法指南 以下是内核开发中最实用的快速调试技巧,按优先级排序(从最快捷到进阶): --- #### 1. **printk + dmesg 组合**(最基础高效) ```c // 在需要调试的位置插入 printk(KERN_DEBUG "Debug: var_x=%d, addr=%p\n", var_x, ptr); ``` - **查看输出**: ```bash dmesg -wH | grep "Debug:" # 实时跟踪带标记的日志 ``` - **优势**:零配置成本,适用于所有内核版本[^1] - **技巧**: - 使用 `KERN_DEBUG` 级别避免刷屏 - 插入函数边界标记:`printk("---- %s ENTER ----\n", __func__);` --- #### 2. **dump_stack() 动态追踪**(定位调用路径) ```c if (unlikely(error_condition)) { printk(KERN_ALERT "Error detected!\n"); dump_stack(); // 打印当前调用栈 } ``` - **输出示例**: ``` [ 123.456] Call Trace: [ 123.457] [<ffffffff812a8e04>] do_syscall_64+0x34/0x80 [ 123.458] [<ffffffff8100116a>] setup_something+0x2a/0xc0 ``` - **解析技巧**: ```bash cat /proc/kallsyms | grep ffffffff8100116a # 解析地址对应函数名 ``` 输出:`ffffffff8100116a T setup_something`[^2] --- #### 3. **OOPS 消息自动分析**(崩溃现场) 当内核崩溃时自动触发: 1. 保存 `/var/log/kern.log` 中的 OOPS 消息 2. **关键信息定位**: ``` PC is at snd_soc_dai_set_sysclk+0x10/0x84 ``` - `snd_soc_dai_set_sysclk`:崩溃函数 - `+0x10`:函数内偏移量 - `0x84`:函数总长度 3. **反汇编定位代码行**: ```bash objdump -d vmlinux | grep -A 20 "snd_soc_dai_set_sysclk" ``` 查找 `0x10` 偏移处的指令[^3] --- #### 4. **ftrace 动态跟踪**(无需重启) ```bash # 启用函数跟踪 echo function > /sys/kernel/debug/tracing/current_tracer echo 1 > /sys/kernel/debug/tracing/tracing_on # 过滤特定函数 echo "my_*" > set_ftrace_filter # 捕获数据 cat trace > /tmp/debug.log ``` - **优势**:实时跟踪函数调用关系,性能开销低[^1] - **输出解析**: ``` my_driver-152 [000] ...1 123.456789: my_function <-caller_function ``` --- #### 5. **kprobe 动态插桩**(高级调试) ```c #include <linux/kprobes.h> static struct kprobe kp = { .symbol_name = "target_function", }; static int handler_pre(struct kprobe *p, struct pt_regs *regs) { printk("Enter %s, arg0=0x%lx\n", p->symbol_name, regs->di); return 0; } // 模块初始化中注册 register_kprobe(&kp); ``` - **作用**:在任意函数入口插入调试逻辑 - **优势**:无需修改目标函数代码[^1] --- ### 调试方法对比表 | 方法 | 准备时间 | 实时性 | 适用场景 | |---------------|----------|--------|---------------------------| | printk | <1分钟 | 中 | 变量检查、流程跟踪 | | dump_stack | <1分钟 | 高 | 函数调用路径分析 | | OOPS分析 | 5分钟 | 事后 | 内核崩溃现场还原 | | ftrace | 3分钟 | 高 | 函数调用关系/耗时分析 | | kprobe | 10分钟 | 高 | 第三方函数参数监控 | > **黄金法则**:80%的问题可通过 `printk + dump_stack` 解决;复杂问题用 `ftrace`;崩溃分析首选 OOPS。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值