4. ftrace 核心概念:tracer、trace event、filter、trigger、instance

ftrace 是 Linux 内核内置的跟踪框架,其设计围绕五个核心概念展开:tracer(跟踪器)、trace event(跟踪事件)、filter(过滤)、trigger(触发)和 instance(实例)。理解这五个概念是掌握 ftrace 调试能力的基础。

4.1 Tracer(跟踪器)

Tracer 是 ftrace 中最上层的抽象,它定义了一种特定的数据采集模式。每个 tracer 对应一个内核子系统或一种跟踪策略,通过 /sys/kernel/tracing/current_tracer 文件选择激活。

Tracer 名称 功能描述 典型场景
function 跟踪所有内核函数的调用入口和返回 函数调用路径分析、性能热点定位
function_graph 以调用图形式显示函数嵌套关系,包含执行时间 函数耗时分析、调用链可视化
nop 空跟踪器,不采集任何数据 关闭跟踪、释放资源
irqsoff 跟踪中断被关闭的最大时长 实时性分析、中断延迟排查
preemptoff 跟踪抢占被关闭的最大时长 实时性分析、调度延迟排查
wakeup 跟踪高优先级任务从唤醒到获得 CPU 的延迟 调度延迟测量、RT 任务性能
关键操作:切换 tracer 后,跟踪数据写入 trace 文件,可通过 cat /sys/kernel/tracing/trace 读取。
提示:function_graph 是日常调试中使用频率最高的 tracer,它同时提供函数调用关系和执行时间,适合快速定位性能瓶颈。
Tracer 选择与数据流 用户空间 current_tracer Tracer 引擎 数据采集 trace 文件 用户读取 用户通过 current_tracer 选择 tracer,数据采集后写入 trace 文件供读取 切换 tracer 会自动清空之前的跟踪数据

4.2 Trace Event(跟踪事件)

Trace event 是 ftrace 中最细粒度的数据采集单元。与 tracer 不同,trace event 由内核代码中的 tracepoint 静态定义,每个事件对应一个特定的内核行为(如系统调用、调度切换、中断触发)。

事件通过 /sys/kernel/tracing/events/ 目录组织,按子系统分组:

# 查看所有可用事件子系统
ls /sys/kernel/tracing/events/

# 启用特定事件(以 syscalls 子系统为例)
echo 1 > /sys/kernel/tracing/events/syscalls/sys_enter_openat/enable

# 启用整个子系统
echo 1 > /sys/kernel/tracing/events/syscalls/enable
子系统 事件示例 用途
syscalls sys_enter_openat, sys_exit_read 系统调用跟踪
sched sched_switch, sched_wakeup 调度行为分析
irq irq_handler_entry, irq_handler_exit 中断处理跟踪
block block_rq_complete, block_rq_insert 块设备 I/O 分析
kmem kmalloc, kfree 内存分配跟踪
注意:启用过多事件会导致跟踪数据量激增,可能引发性能下降或环形缓冲区溢出。建议先通过 filter 缩小范围,再启用事件。
Trace Event 层级结构 events/ syscalls/ sched/ irq/ block/ sys_enter_open sys_exit_read sched_switch irq_handler_entry 每个事件目录下包含 enable、filter、trigger 等控制文件 事件启用后,每次触发都会记录一条包含时间戳、PID、CPU 的跟踪记录

4.3 Filter(过滤)

Filter 机制允许用户对 trace event 设置条件表达式,只有满足条件的事件才会被记录。这在大规模跟踪时能有效减少数据量,聚焦目标行为。

Filter 通过事件目录下的 filter 文件配置,支持对事件字段进行逻辑运算:

# 只记录 PID 为 1234 的进程的系统调用
echo "common_pid == 1234" > /sys/kernel/tracing/events/syscalls/sys_enter_openat/filter

# 复合条件:PID 为 1234 且返回值大于 0
echo "common_pid == 1234 && ret > 0" > /sys/kernel/tracing/events/syscalls/sys_exit_openat/filter

# 清除 filter
echo 0 > /sys/kernel/tracing/events/syscalls/sys_enter_openat/filter
操作符 说明 示例
== 等于 common_pid == 100
!= 不等于 common_pid != 0
> / < 大于 / 小于 latency > 1000
&& / || 逻辑与 / 或 pid == 100 && cpu == 0
~ 正则匹配(字符串字段) comm ~ "sshd"
最佳实践:先启用事件,观察原始数据中的字段名,再编写 filter 表达式。常用字段包括 common_pid(进程 PID)、common_comm(进程名)、cpu(CPU 编号)。

4.4 Trigger(触发)

Trigger 是 ftrace 的事件驱动机制,允许在事件触发时执行预定义的动作。Trigger 通过事件目录下的 trigger 文件配置,支持多种动作类型。

Trigger 类型 动作 典型用法
traceon 事件触发时开启跟踪 条件触发后开始记录
traceoff 事件触发时关闭跟踪 捕获特定事件后停止
snapshot 事件触发时保存当前跟踪缓冲区快照 保留异常时刻的上下文
enable_event 事件触发时启用另一个事件 级联跟踪
disable_event 事件触发时禁用另一个事件 动态控制事件开关
stacktrace 事件触发时记录内核栈回溯 定位调用路径
# 当 sched_switch 事件触发时,记录内核栈
echo 'stacktrace' > /sys/kernel/tracing/events/sched/sched_switch/trigger

# 当 sys_enter_openat 触发时,启用 sys_exit_openat 事件
echo 'enable_event:syscalls:sys_exit_openat' > /sys/kernel/tracing/events/syscalls/sys_enter_openat/trigger

# 清除所有 trigger
echo '!stacktrace' > /sys/kernel/tracing/events/sched/sched_switch/trigger
注意:Trigger 动作会引入额外开销,特别是 stacktrace 和 snapshot。在生产环境中使用时需评估性能影响。

4.5 Instance(实例)

Instance 是 ftrace 的隔离机制,允许创建多个独立的跟踪上下文。每个 instance 拥有独立的缓冲区、tracer 和事件配置,互不干扰。这在同时调试多个子系统或多个进程时极为有用。

Instance 通过 /sys/kernel/tracing/instances/ 目录管理:

# 创建新实例
mkdir /sys/kernel/tracing/instances/my_instance

# 在实例中配置 tracer
echo function_graph > /sys/kernel/tracing/instances/my_instance/current_tracer

# 在实例中启用事件
echo 1 > /sys/kernel/tracing/instances/my_instance/events/sched/sched_switch/enable

# 读取实例的跟踪数据
cat /sys/kernel/tracing/instances/my_instance/trace

# 删除实例
rmdir /sys/kernel/tracing/instances/my_instance
特性 默认实例(top-level) 自定义实例
缓冲区 全局共享 独立分配
配置隔离 全局生效 实例内独立
性能影响 所有事件共享开销 仅影响实例内事件
适用场景 单一目标调试 多目标并行调试
提示:使用 instance 时,每个实例的 trace 文件独立,可以同时运行多个 cat 命令读取不同实例的数据,实现并行监控。
Instance 隔离架构 默认实例 缓冲区: 全局共享 Tracer: function 事件: syscalls 实例: sched_trace 缓冲区: 独立 4MB Tracer: function_graph 事件: sched_switch 实例: irq_trace 缓冲区: 独立 2MB Tracer: nop 事件: irq_handler 内核跟踪框架 (ftrace core) 每个实例拥有独立的 trace、current_tracer、events 等控制文件 实例之间完全隔离,一个实例的配置不会影响其他实例

4.6 五者协同工作流

在实际调试中,这五个概念通常协同使用,形成完整的数据采集链路:

  1. 选择 tracer:通过 current_tracer 确定数据采集模式(如 function_graph)。
  2. 启用事件:在 events/ 下选择需要跟踪的具体事件。
  3. 设置 filter:对事件字段添加条件,只记录目标数据。
  4. 配置 trigger:定义事件触发时的附加动作(如 stacktrace)。
  5. 使用 instance:为不同调试目标创建隔离的跟踪上下文。
实战示例:同时跟踪两个进程的系统调用和调度行为,使用两个 instance 分别配置,互不干扰。
# 创建两个实例
mkdir /sys/kernel/tracing/instances/proc_a
mkdir /sys/kernel/tracing/instances/proc_b

# 实例 A:跟踪进程 100 的系统调用
echo 1 > /sys/kernel/tracing/instances/proc_a/events/syscalls/enable
echo "common_pid == 100" > /sys/kernel/tracing/instances/proc_a/events/syscalls/filter

# 实例 B:跟踪进程 200 的调度事件
echo 1 > /sys/kernel/tracing/instances/proc_b/events/sched/enable
echo "common_pid == 200" > /sys/kernel/tracing/instances/proc_b/events/sched/filter

# 分别读取数据
cat /sys/kernel/tracing/instances/proc_a/trace
cat /sys/kernel/tracing/instances/proc_b/trace

通过这种组合方式,ftrace 能够以极低的性能开销实现高度定制化的内核行为跟踪,满足从性能分析到故障定位的多种调试需求。