3. Linux 内核测量工具:perf、ftrace、trace-cmd 的基本使用与性能数据采集

在嵌入式 Linux 驱动性能优化中,测量是优化的前提。内核提供了三把利器:perf(性能计数器与采样)、ftrace(函数级跟踪)、trace-cmd(ftrace 的前端封装)。本章将系统讲解这三者的核心原理、基本用法以及如何采集驱动性能数据。

学习目标:掌握 perf 的 stat/record/report 命令、ftrace 的 tracefs 接口与 function_graph 跟踪器、trace-cmd 的 record/report 工作流,并能独立完成一次驱动中断延迟或函数耗时测量。

3.1 perf:性能计数器与采样分析

perf 基于 Performance Monitoring Unit (PMU) 硬件,能以极低开销统计 CPU 周期、缓存命中率、分支预测失败等硬件事件,也支持软件事件(如上下文切换、缺页中断)。

3.1.1 常用子命令与事件分类

子命令 功能 典型场景
perf stat 运行命令并统计硬件/软件事件计数 对比优化前后的总周期数、指令数
perf record 采样事件并写入 perf.data 定位热点函数、调用链
perf report 解析 perf.data 并展示采样结果 查看函数 CPU 占用百分比
perf top 实时显示当前系统热点函数 快速定位驱动中断处理中的高耗时路径
perf list 列出当前 CPU 支持的所有事件 确认硬件事件名称

3.1.2 驱动性能数据采集实战

场景:测量某 SPI 驱动在传输 1KB 数据时的 CPU 周期数与指令数。

# 1. 统计硬件事件
perf stat -e cycles,instructions,cache-misses \
  dd if=/dev/spidev0.0 of=/dev/null bs=1024 count=1

# 2. 采样热点函数(频率 1000Hz,持续 5 秒)
perf record -F 1000 -g -p $(pidof spi_driver) -- sleep 5

# 3. 查看采样报告
perf report --stdio --sort symbol
关键指标解读:
  • CPI (Cycles Per Instruction) = cycles / instructions。理想值接近 1.0,若 > 2.0 说明存在严重的流水线停顿或缓存未命中。
  • cache-misses / cache-references 比率 > 5% 时,应考虑数据对齐或预取优化。

3.1.3 perf 驱动性能分析流程图

perf 驱动性能分析流程 perf 驱动性能分析流程 perf stat 事件计数 perf record 采样 + 调用链 perf report 热点分析 perf top 实时热点 perf list 事件枚举 💡 驱动优化切入点 • 中断处理函数(ISR)中避免使用 printk、kmalloc 等耗时操作 • 使用 per-CPU 变量减少锁竞争,观察 perf 中的 spin_lock 热点 • 检查 cache-misses 是否因数据结构跨 cache line 导致

3.2 ftrace:函数级跟踪与延迟测量

ftrace 是内核内置的跟踪框架,通过 tracefs(挂载于 /sys/kernel/tracing)提供用户态接口。它支持多种跟踪器,其中 function_graph 能记录函数调用关系与执行时间,是驱动延迟分析的利器。

3.2.1 ftrace 核心文件与配置

文件路径 作用 常用值
current_tracer 选择当前跟踪器 function_graph, function, nop
set_ftrace_filter 只跟踪指定函数(支持通配符) spi_*, my_driver_irq_handler
set_ftrace_notrace 排除不需要跟踪的函数 schedule, __do_softirq
tracing_on 开关跟踪(1 开启,0 关闭) 1, 0
trace 读取跟踪结果 cat 查看
trace_pipe 流式读取跟踪结果(阻塞) cat 持续输出

3.2.2 测量驱动中断处理函数耗时

# 1. 挂载 tracefs
mount -t tracefs tracefs /sys/kernel/tracing
cd /sys/kernel/tracing

# 2. 清空之前的跟踪
echo nop > current_tracer
echo > trace

# 3. 设置 function_graph 跟踪器,只跟踪中断处理函数
echo function_graph > current_tracer
echo my_irq_handler > set_ftrace_filter

# 4. 开启跟踪
echo 1 > tracing_on

# 5. 触发一次中断(例如发送 SPI 数据)
spi_send_data

# 6. 关闭跟踪并查看结果
echo 0 > tracing_on
cat trace
注意事项:
  • 生产环境开启 ftrace 会增加函数调用开销(约 0.5~2 µs/次),建议只过滤关键函数。
  • 使用 trace_pipe 时注意缓冲区溢出,可配合 buffer_size_kb 调整大小。
  • ARM64 平台需确保内核配置 CONFIG_FUNCTION_GRAPH_TRACER=y。

3.2.3 ftrace function_graph 输出示例

# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
 0)   3.125 us   |  my_irq_handler();
 0)   1.002 us   |    readl();
 0)   0.503 us   |    writel();
 0)   0.750 us   |    my_clear_interrupt();
 0)   4.380 us   |  } /* my_irq_handler */

从输出可见:中断处理函数总耗时 4.38 µs,其中 readl 占 1.0 µs,writel 占 0.5 µs。若总耗时超过 10 µs,应考虑将部分工作移至 tasklet 或 workqueue。

3.3 trace-cmd:ftrace 的前端封装

trace-cmd 是对 ftrace 的封装,提供更友好的命令行接口,支持 记录(record)、报告(report)、流式输出(stream)等操作。它自动处理 tracefs 的配置与清理,适合脚本化采集。

3.3.1 trace-cmd 基本工作流

步骤 命令 说明
1. 记录跟踪数据 trace-cmd record -p function_graph -l my_irq_handler ./test_app 运行 test_app 并记录其内核函数调用
2. 查看报告 trace-cmd report 解析 trace.dat 并输出可读结果
3. 流式监控 trace-cmd stream -p function_graph -l my_irq_handler 实时输出跟踪数据,类似 trace_pipe
4. 提取特定事件 trace-cmd report -F 'irq_handler_entry' 只显示中断入口事件

3.3.2 采集驱动中断延迟数据

# 记录 10 秒内所有中断相关事件
trace-cmd record -e irq:irq_handler_entry -e irq:irq_handler_exit \
  -T -F 'common_pid != 0' sleep 10

# 查看每个中断处理函数的耗时
trace-cmd report --cpu-time | grep "irq_handler"
trace-cmd 优势:
  • 自动处理 tracefs 挂载与权限,无需手动 echo 配置。
  • 支持 事件过滤(-F)和 函数过滤(-l),减少数据量。
  • 输出格式统一,便于脚本解析(如 --ts2sec 转换时间戳)。

3.4 三款工具对比与选型

维度 perf ftrace trace-cmd
主要用途 硬件事件计数、采样热点 函数调用跟踪、延迟分析 ftrace 的易用封装
开销 极低(硬件 PMU) 中等(函数级插桩) 同 ftrace
适用场景 CPU 利用率、缓存优化 中断延迟、驱动函数耗时 自动化脚本、批量采集
输出格式 二进制 perf.data 文本 trace 二进制 trace.dat
内核配置要求 CONFIG_PERF_EVENTS=y CONFIG_FUNCTION_TRACER=y 同 ftrace + CONFIG_TRACING=y

3.5 综合数据采集策略

在实际驱动优化中,建议按以下流程组合使用三款工具:

  1. perf top 快速扫描,定位 CPU 占用最高的驱动函数。
  2. perf record/report 深入分析热点函数的调用链与 CPI。
  3. ftrace function_graph 测量关键函数的精确耗时,确认延迟瓶颈。
  4. trace-cmd record 在自动化测试中批量采集,对比优化前后的数据。
实战建议:在嵌入式板卡上,优先使用 perf stat 做快速评估,因为其开销最小。当需要定位具体函数时,再切换到 ftrace 或 trace-cmd,并务必使用 set_ftrace_filter 缩小跟踪范围,避免跟踪缓冲区溢出导致系统卡顿。