参考来源与版权说明
这章解决什么问题
Ftrace 是内核自带的跟踪工具箱,适合回答“某个内核函数调用多频繁”“什么路径调用了它”“它又调用了哪些子函数”“内核或外部扰动造成的延时有多大”。它没有强制依赖复杂用户程序,因此在服务器和受限环境都很实用。
困难不在启动跟踪,而在选对事件并控制成本。函数剖析输出统计摘要;函数、function_graph、tracepoint、kprobe/uprobe 输出逐事件细节;hist 触发器在内核内聚合。应先计数、后跟踪,先稳定 tracepoint、后动态探针。
五条核心结论
- tracefs 是控制面。 available_tracers、events、trace、trace_pipe 等文件连接内核事件与用户空间。
- 剖析器给摘要,跟踪器给事件。 摘要开销通常更低,适合先判断频率和热点。
- tracepoint 优先于动态探针。 静态事件接口相对稳定;kprobe/uprobe 依赖函数、偏移、ABI 和版本。
- trace 与 trace_pipe 语义不同。 trace 是环形缓冲区快照;trace_pipe 是消费式实时流,读走后事件不再留在缓冲区。
- 范围和频率决定风险。 高频函数的逐调用跟踪可能严重扰动系统;过滤 PID、函数、字段、CPU 和时长是基本纪律。
核心模型与关键指标
Ftrace 的数据路径可以概括为:
~~~text
事件源
├─ 函数入口:function / function_graph
├─ 静态事件:tracepoint
├─ 动态事件:kprobe / uprobe
└─ 特殊跟踪器:hwlat 等
↓ 过滤、触发、hist 聚合
每 CPU 环形缓冲区
↓
trace(快照)/ trace_pipe(实时消费)/ trace-cmd 的 trace.dat
~~~
函数剖析常看 Hit、总时间、平均时间和离散程度;逐事件跟踪看时间戳、CPU、进程/PID、标志与参数。function_graph 还显示嵌套调用和持续时间。数据质量要检查缓冲区大小、entries written、overrun/dropped、过滤器是否命中,以及观测带来的额外延时。
hwlat 会在禁用中断的循环中寻找内核不可见的时间缺口,可提示 SMI 或虚拟化扰动,但它主动占用 CPU 并禁用中断,属于会扰动系统的实验工具,不应当作普通只读监控。
多用户环境还要考虑实例隔离。tracefs 的 instances 目录允许不同调查拥有独立的 current_tracer、事件开关和缓冲区,避免两个人互相清空结果。实例并不能消除底层探针开销,但能隔离控制状态和输出。若发行版或前端不支持实例,应在操作前记录当前状态,并明确谁负责恢复。
诊断步骤
- 确认 tracefs 挂载位置;新系统常在 <code>/sys/kernel/tracing</code>,旧路径常为 <code>/sys/kernel/debug/tracing</code>。
- 只读查看 available_tracers、current_tracer 与 events,确认目标在本机存在。
- 先用函数剖析、perf stat 或现成工具估算事件率;高频事件优先做 hist 聚合。
- 优先选择语义稳定的 tracepoint,并用 PID/字段/CPU 过滤器缩小范围。
- 以 5–10 秒短窗口记录到文件,避免长时间盯着实时流;必要时才启用调用图或栈。
- 检查丢事件和跟踪状态;保存内核版本、命令、过滤器与 trace.dat,并让前端负责清理临时状态。
若问题是“错误发生前发生了什么”,可以使用触发器在条件命中时停止跟踪或保存 snapshot,让环形缓冲区保留事前上下文。若问题是分布,优先用 hist 在内核中按 PID、字段或栈聚合。两者都应先在测试环境核对过滤字段,并准备删除触发器的清理步骤。
常用工具与命令
下面先列只读检查,再给有明确时限的记录。trace-cmd/perf ftrace 通常需要特权,会短暂启用内核跟踪并在结束后恢复状态;trace-cmd 会生成 trace.dat。
~~~bash
# 查找挂载点并查看当前能力(只读)
mount -t debugfs,tracefs
cat /sys/kernel/tracing/available_tracers
cat /sys/kernel/tracing/current_tracer
# 旧内核/发行版可能使用此路径
cat /sys/kernel/debug/tracing/available_tracers
# 用前端列出事件并记录调度切换 10 秒
trace-cmd list -e
trace-cmd record -e sched:sched_switch sleep 10
trace-cmd report
# 跟踪一个内核函数的调用图,持续 10 秒
trace-cmd record -p function_graph -g do_nanosleep sleep 10
trace-cmd report
# perf 对 Ftrace 的轻量封装;选项随版本变化
perf ftrace -T do_nanosleep -a -- sleep 10
~~~
书中还展示了直接向 tracefs 写控制文件的做法。那会改变全局或实例的跟踪状态,若忘记关闭/清理会影响其他人;生产排障优先使用 trace-cmd、独立 instances 或经过审计的脚本。
如何解读结果
普通跟踪行先看进程/PID、CPU 与时间戳,再看事件和参数;不要把“事件在某 CPU 上发生”误解成请求始终由该 CPU 处理。function_graph 中缩进表达调用层次,左侧持续时间包括被跟踪子调用及跟踪开销;只过滤目标函数后时间往往更接近真实值。
tracepoint 的 format 文件是字段权威来源,过滤器必须按本机字段编写。hist 的 Hits 是写入次数,Entries 是键数量,Dropped 表示哈希空间不足;出现 Dropped 时,分布不完整。综合事件能把开始与结束按键关联计算延时,但键选错、事件丢失或跨线程行为都会产生错误配对。
环形缓冲区只保留有限历史。entries-written 大于当前 entries 表示更早事件可能已被覆盖;实时输出跟不上生产速度也可能造成观测盲区。因此“没看到”只能在确认事件启用、过滤命中、缓冲未溢出和读取窗口覆盖之后,才能作为“没发生”的证据。
常见误判
- 在没计数前跟踪每秒数十万次的函数,把性能问题变成观测开销问题。
- 把 kprobe 函数名、寄存器参数或 uprobe 偏移从另一内核/二进制直接照搬。
- 直接读 trace_pipe 后又期望在 trace 中看到同一批事件。
- function_graph 不设范围就跟踪全部子函数,并把放大的持续时间当真实业务延时。
- 把 hwlat 当作无干扰监控;它本身会占用 CPU 并禁用中断。
- 忘记清理全局跟踪状态,或与另一位使用者共享同一个缓冲区。
五分钟自测
- 只想知道函数调用次数,为什么应先选剖析而非逐事件跟踪?
- trace 与 trace_pipe 的读取差异是什么?
- 为什么 tracepoint 通常比 kprobe 更适合长期脚本?
- function_graph 的持续时间为何可能偏大?
- hist 输出出现 Dropped 说明什么?
检查要点:更低开销;快照与消费流;静态接口更稳定;记录所有子调用会增加开销;哈希容量不足导致部分键未保存。
本章小结
Ftrace 的安全用法是“只读发现能力 → 低成本计数 → 稳定事件与严格过滤 → 短时记录 → 检查丢失并恢复状态”。tracefs 提供底层能力,trace-cmd、perf ftrace 和专用工具降低操作风险;需要复杂聚合时再选择 hist 或 BPF。
来源定位
| 主题 | PDF 页码 |
|---|---|
| 功能概览、tracefs 与函数剖析 | 752-759 |
| 函数跟踪、trace/trace_pipe 与 tracepoint | 759-766 |
| kprobe、uprobe 与 function_graph | 766-773 |
| hwlat、hist 与综合事件 | 773-781 |
| trace-cmd、KernelShark、perf ftrace | 781-788 |
| perf-tools、开销比较与文档 | 788-796 |
章节测验
共 5 道单选题。答错有解析,答对看来源页码。