Ftrace 是 Linux 内核内置的追踪框架,不需要额外安装,开销比 strace 和 perf 都低,适合生产环境的内核级追踪。
一、Ftrace vs perf vs strace:什么时候选谁
| | |
|---|
| perf | |
| Ftrace | |
| strace | |
| Ftrace | |
| Ftrace | |
| perf | |
核心差异:Ftrace 是"内核里的探照灯",低开销看内核在干什么;perf 是"全能分析仪",覆盖用户态和内核态但开销稍高;strace 是"系统调用放大镜",易用但会显著拖慢被追踪程序。
二、trace-cmd:Ftrace 的生产环境入口
trace-cmd 是 Ftrace 的用户态工具,比直接操作 /sys/kernel/debug/tracing/ 更安全:
# 安装centos: yum install trace-cmdubuntu: apt-get install trace-cmd# 查看可用追踪器trace-cmd list# 记录函数追踪trace-cmd record -p function -l 'tcp_sendmsg' -l 'tcp_recvmsg'# 查看报告trace-cmd report# 启动图形界面(KernelShark)trace-cmd report | kernelshark
2.1 常用 trace-cmd 场景
# 场景1:追踪调度事件(排查调度延迟)trace-cmd record -e sched:sched_switch -e sched:sched_wakeup# 分析:看进程被唤醒到实际执行的时间差# 场景2:追踪 I/O 事件(排查磁盘延迟)trace-cmd record -e block:block_rq_issue -e block:block_rq_complete# 分析:看 I/O 从发起到完成的耗时# 场景3:追踪网络事件(排查网络延迟)trace-cmd record -e net:net_dev_queue -e net:net_dev_xmit# 场景4:函数调用链追踪trace-cmd record -p function_graph -g 'tcp_sendmsg'# -p function_graph: 显示函数进入/退出时间# -g: 追踪该函数及其内部调用# 场景5:过滤特定进程trace-cmd record -e sched:sched_switch --pid $(pgrep mysqld)
三、tracefs 直接操作:更灵活,但更危险
tracefs 通常挂载在 /sys/kernel/debug/tracing/,可以直接读写控制追踪行为:
# ===== 基础操作 =====# 查看可用追踪器cat /sys/kernel/debug/tracing/available_tracers# 输出: function function_graph blk mmiotrace wakeup ...# 启用函数追踪器echo function > /sys/kernel/debug/tracing/current_tracer# 追踪特定函数echo '__do_page_fault' > /sys/kernel/debug/tracing/set_ftrace_filter# 开始追踪echo 1 > /sys/kernel/debug/tracing/tracing_on# 查看结果cat /sys/kernel/debug/tracing/trace | head -100# 停止追踪echo 0 > /sys/kernel/debug/tracing/tracing_on# 清空缓冲区echo > /sys/kernel/debug/tracing/trace# ===== 高级过滤 =====# 按进程过滤echo $(pgrep mysqld) > /sys/kernel/debug/tracing/set_ftrace_pid# 设置追踪深度(防止调用链太深)echo 5 > /sys/kernel/debug/tracing/max_graph_depth# 启用时间戳echo 1 > /sys/kernel/debug/tracing/options/trace_printk# 只追踪超过 X 微秒的函数echo 1000 > /sys/kernel/debug/tracing/tracing_thresh # 1000us = 1ms
四、Histogram:延迟分布统计的隐藏利器
Ftrace 的 hist 触发器可以按条件聚合事件,生成延迟直方图——这个功能很多人不知道,但非常实用:
# 追踪 sched_switch 事件,按进程名聚合,统计运行时间分布echo 'hist:keys=next_comm.comm:vals=hitcount:ts0=common_timestamp.usecs if next_comm == "mysqld"' > \ /sys/kernel/debug/tracing/events/sched/sched_switch/trigger# 查看结果cat /sys/kernel/debug/tracing/events/sched/sched_switch/hist# 清除触发器echo '!hist:keys=next_comm.comm:vals=hitcount:ts0=common_timestamp.usecs' > \ /sys/kernel/debug/tracing/events/sched/sched_switch/trigger
典型应用:- 统计特定进程的调度延迟分布- 统计 I/O 请求的完成时间分布- 统计网络包的传输延迟
# I/O 延迟直方图示例echo 'hist:keys=dev:vals=hitcount:ts0=common_timestamp.usecs' > \ /sys/kernel/debug/tracing/events/block/block_rq_complete/trigger
五、Ftrace 生产环境使用指南
5.1 安全使用原则
| |
|---|
| 先过滤再追踪 | 不加过滤直接 function 追踪会产生巨量数据,可能拖垮系统 |
| 限制追踪深度 | max_graph_depth=5 |
| 设置时间阈值 | tracing_thresh=1000 |
| 限制缓冲区大小 | buffer_size_kb=4096 |
| 先测试环境验证 | |
# 生产环境安全配置脚本#!/bin/bashecho "=== Ftrace 安全配置 ==="# 设置缓冲区大小(4MB)echo 4096 > /sys/kernel/debug/tracing/buffer_size_kb# 设置最大追踪深度echo 5 > /sys/kernel/debug/tracing/max_graph_depth# 设置时间阈值(只追踪 >1ms 的)echo 1000 > /sys/kernel/debug/tracing/tracing_thresh# 清空之前的过滤echo > /sys/kernel/debug/tracing/set_ftrace_filterecho > /sys/kernel/debug/tracing/set_ftrace_pid# 选择追踪器echo function_graph > /sys/kernel/debug/tracing/current_tracerecho "配置完成。现在添加过滤条件后启用追踪。"
5.2 常用诊断场景速查
| | |
|---|
| sched:sched_switch | |
| block:block_rq_issue + block:block_rq_complete | |
| net:net_dev_queue | |
| function_graph | |
| raw_syscalls:sys_enter | |
五个常见误区
| | |
|---|
| ❌ "Ftrace 比 perf 好,都用 Ftrace" | ✅ 两者互补,Ftrace 擅长内核追踪,perf 擅长硬件事件 | |
| | |
| ❌ "trace-cmd 比 tracefs 慢" | ✅ trace-cmd 是对 tracefs 的封装,性能一样 | |
| | 检查 /sys/kernel/debug/tracing 的权限 |
| | |
总结
Ftrace 的三条使用原则:
- 优先用 trace-cmd
- 先用 function_graph 看调用链
- Histogram 是隐藏利器
带走的东西:需要看内核在干什么,但 perf 太重时——用 Ftrace。