以下是使用 Ftrace 调试 Linux 内核的完整示例,涵盖常用场景和操作步骤:
1. 基础函数跟踪
场景:跟踪 schedule() 函数的调用情况。
# 挂载 tracefs(如果未自动挂载)
mount -t tracefs nodev /sys/kernel/tracing
# 进入 trace 目录
cd /sys/kernel/tracing
# 启用函数跟踪器
echo function > current_tracer
# 设置要跟踪的函数
echo schedule > set_ftrace_filter
# 开始记录
echo 1 > tracing_on
# 触发一些操作(例如运行一个进程)
sleep 1
# 停止记录
echo 0 > tracing_on
# 查看结果
cat trace
输出示例:
# tracer: function
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
sleep-1234 [001] 12345.678901: schedule <-do_nanosleep
bash-5678 [002] 12345.678902: schedule <-schedule_timeout
2. 跟踪特定进程
场景:仅跟踪 PID 为 1234 的进程调用的函数。
# 设置 PID 过滤
echo 1234 > set_ftrace_pid
# 启用跟踪
echo function > current_tracer
echo 1 > tracing_on
# 查看结果
cat trace
3. 跟踪函数调用关系(函数图)
场景:分析 do_sys_open() 的调用栈。
# 启用函数图跟踪器
echo function_graph > current_tracer
# 设置跟踪函数
echo do_sys_open > set_graph_function
# 开始记录
echo 1 > tracing_on
# 执行文件操作(如 `cat /proc/version`)
cat /proc/version
# 停止并查看
echo 0 > tracing_on
cat trace
输出示例:
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
1) 1.234 us | do_sys_open();
1) | getname() {
1) 0.567 us | getname_flags();
1) 1.234 us | }
1) | vfs_open() {
1) 0.456 us | do_dentry_open();
1) 2.345 us | }
4. 跟踪内核模块函数
场景:跟踪自定义模块 my_module 中的 my_func()。
# 确保模块已加载且符号可见
grep my_func /proc/kallsyms
# 设置过滤器
echo ':mod:my_module' > set_ftrace_filter
echo my_func >> set_ftrace_filter
# 启用跟踪
echo function > current_tracer
echo 1 > tracing_on
# 触发模块函数调用
# ...
# 查看结果
cat trace
5. 跟踪中断事件
场景:跟踪 IRQ 事件和中断处理函数。
# 启用中断事件跟踪
echo irq:* > set_event
# 同时跟踪中断处理函数
echo handle_irq_event_percpu > set_ftrace_filter
# 开始记录
echo 1 > tracing_on
# 触发中断(如网卡收包)
ping -c 1 google.com
# 停止并查看
echo 0 > tracing_on
cat trace
输出示例:
# tracer: function
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [000] d... 1234.567890: irq_handler_entry: irq=19 name=eth0
<idle>-0 [000] d... 1234.567891: handle_irq_event_percpu <-handle_irq_event
6. 跟踪内核锁事件
场景:分析自旋锁的竞争情况。
# 启用锁事件跟踪
echo lock:* > set_event
# 开始记录
echo 1 > tracing_on
# 触发锁操作(如并发访问驱动)
# ...
# 停止并查看
echo 0 > tracing_on
cat trace | grep spin_lock
7. 使用 trace-cmd 简化操作
场景:一键记录并分析函数调用。
# 安装 trace-cmd
sudo apt install trace-cmd
# 记录 schedule 函数的调用
trace-cmd record -p function -l schedule
# 生成报告
trace-cmd report
8. 高级技巧
(1) 过滤函数调用时长
# 只显示执行时间 > 100us 的函数
echo duration > trace_options
echo 100 > tracing_thresh # 单位微秒
(2) 跟踪内核定时器
echo hrtimer:* > set_event
echo timer:* >> set_event
(3) 保存跟踪结果
cat trace > /tmp/ftrace.log
9. 恢复默认配置
# 停止跟踪
echo 0 > tracing_on
# 重置跟踪器
echo nop > current_tracer
# 清空过滤器
echo > set_ftrace_filter
echo > set_event
总结表
| 场景 | 关键命令 | 输出内容 |
|---|---|---|
| 基础函数跟踪 | echo function > current_tracer | 函数调用顺序和时间戳 |
| 函数调用栈 | echo function_graph > current_tracer | 函数嵌套关系和耗时 |
| 进程过滤 | echo PID > set_ftrace_pid | 仅目标进程的函数调用 |
| 模块函数跟踪 | echo ':mod:module' > set_ftrace_filter | 模块内特定函数的调用 |
| 中断跟踪 | echo irq:* > set_event | 中断触发和处理流程 |
通过灵活组合这些方法,可以高效诊断内核行为、性能瓶颈和竞态条件问题。
962

被折叠的 条评论
为什么被折叠?



