4. ftrace 基础配置:挂载 tracefs、可用追踪器列表、current_tracer 设置

ftrace 是 Linux 内核内置的追踪基础设施,其配置入口通过 tracefs 伪文件系统暴露。在开始追踪系统调用之前,必须完成挂载、查看可用追踪器、选择当前追踪器三个基础步骤。本节将逐一演示这些操作,并解释每个步骤背后的内核机制。

4.1 挂载 tracefs 文件系统

tracefs 通常自动挂载于 /sys/kernel/tracing,但在某些发行版或容器环境中需要手动挂载。挂载方式如下:

# 检查是否已挂载
mount | grep tracefs

# 手动挂载 tracefs
mount -t tracefs tracefs /sys/kernel/tracing

# 或使用 debugfs 兼容路径(旧内核)
mount -t debugfs debugfs /sys/kernel/debug
提示: 从内核 4.1 开始,ftrace 推荐使用独立的 tracefs,而非 debugfs。若使用 debugfs,路径为 /sys/kernel/debug/tracing,但功能完全一致。本课程统一使用 /sys/kernel/tracing 路径。

挂载成功后,/sys/kernel/tracing 目录下会出现一系列控制文件和追踪结果文件。下表列出最核心的几个文件及其用途:

文件/目录 用途 读写属性
available_tracers 列出当前内核支持的所有追踪器 只读
current_tracer 设置或查看当前激活的追踪器 读写
tracing_on 全局追踪开关(1 开启,0 关闭) 读写
trace 输出追踪结果(人类可读格式) 只读
trace_pipe 流式输出追踪结果(阻塞读取) 只读
set_event 启用/禁用特定追踪事件 读写
关键概念: tracefs 是一个纯内存文件系统,所有追踪控制通过读写文件完成,无需额外的用户态工具。这种设计使得 ftrace 在嵌入式系统和最小化环境中也能直接使用。
tracefs 挂载与核心文件结构 用户空间 VFS 虚拟文件系统 tracefs 实例 available_tracers current_tracer tracing_on trace / trace_pipe set_event 操作方式 cat available_tracers echo function > current_tracer echo 1 > tracing_on 注意事项 • 所有操作通过文件读写完成 • 无需额外用户态工具

4.2 可用追踪器列表

通过读取 available_tracers 文件,可以查看当前内核编译时启用了哪些追踪器。不同内核配置输出的列表可能不同,以下是一个典型输出:

# cat /sys/kernel/tracing/available_tracers
function_graph function nop

三个追踪器的核心差异如下表所示:

追踪器名称 输出粒度 典型用途 性能开销
nop 无追踪输出 关闭追踪、重置状态 几乎为零
function 每个内核函数入口 函数调用计数、调用频率分析 中等
function_graph 函数入口 + 出口 + 调用深度 函数调用链分析、延迟追踪 较高
注意: 如果 available_tracers 只显示 nop,说明内核编译时未开启 CONFIG_FUNCTION_TRACER 或 CONFIG_FUNCTION_GRAPH_TRACER。此时无法使用 function 和 function_graph 追踪器,需要重新编译内核。

除了上述三个基础追踪器,某些内核还支持以下扩展追踪器(取决于内核配置):

  • wakeup / wakeup_rt / wakeup_dl:追踪进程唤醒延迟,用于实时性分析。
  • irqsoff:追踪中断关闭时间,用于中断延迟分析。
  • preemptoff:追踪抢占关闭时间,用于抢占延迟分析。
  • blk:块设备 I/O 追踪,用于存储性能分析。
  • mmiotrace:内存映射 I/O 追踪,用于驱动调试。
可用追踪器分类与选择流程 读取 available_tracers 包含 function? 是 function 可用 可追踪函数调用 否 仅 nop 可用 需重新编译内核 选择追踪器 echo nop echo function echo function_graph

4.3 current_tracer 设置

current_tracer 文件用于查看或设置当前激活的追踪器。写入追踪器名称即可切换,写入 nop 则关闭追踪。

# 查看当前追踪器
cat /sys/kernel/tracing/current_tracer
nop

# 切换到 function 追踪器
echo function > /sys/kernel/tracing/current_tracer

# 验证切换结果
cat /sys/kernel/tracing/current_tracer
function

# 关闭追踪(重置为 nop)
echo nop > /sys/kernel/tracing/current_tracer
最佳实践: 在切换追踪器之前,建议先执行 echo 0 > tracing_on 暂停追踪,切换完成后再 echo 1 > tracing_on 恢复。这样可以避免在切换过程中产生不完整的追踪记录。

设置 current_tracer 时,内核会执行以下内部操作:

  1. 验证追踪器名称:检查写入的名称是否在 available_tracers 列表中,若不在则返回错误。
  2. 停止当前追踪:自动暂停当前追踪器的数据采集(相当于内部执行 tracing_on = 0)。
  3. 重置缓冲区:清空旧的追踪数据,避免新旧数据混合。
  4. 注册新追踪器回调:将新追踪器的钩子函数挂接到内核函数追踪点。
  5. 恢复追踪:如果之前 tracing_on 为 1,则自动恢复数据采集。

以下是一个完整的配置示例,展示如何从 nop 切换到 function_graph 并验证:

# 步骤1:确认当前状态
cat /sys/kernel/tracing/current_tracer
nop

# 步骤2:暂停追踪
echo 0 > /sys/kernel/tracing/tracing_on

# 步骤3:切换到 function_graph
echo function_graph > /sys/kernel/tracing/current_tracer

# 步骤4:验证切换
cat /sys/kernel/tracing/current_tracer
function_graph

# 步骤5:恢复追踪
echo 1 > /sys/kernel/tracing/tracing_on

# 步骤6:查看追踪输出(前20行)
head -20 /sys/kernel/tracing/trace
常见错误: 如果写入 current_tracer 时出现 write error: Invalid argument,通常是因为写入的追踪器名称不在 available_tracers 列表中,或者当前内核配置不支持该追踪器。请先检查 available_tracers 确认可用列表。
current_tracer 设置内部流程 写入追踪器名称 验证名称合法性 停止当前追踪 重置缓冲区 注册新追踪器回调 恢复追踪(可选) 内部操作细节 • 步骤2:与 available_tracers 列表比对,不匹配则返回 -EINVAL • 步骤3:自动执行 tracing_on = 0,防止切换过程中数据混乱 • 步骤4:清空 trace 缓冲区,确保新旧数据不混合 • 步骤5:将新追踪器的 probe 函数注册到 ftrace 核心框架

4.4 配置验证与常见问题

完成基础配置后,建议通过以下命令验证 ftrace 是否正常工作:

# 验证 tracefs 挂载
ls /sys/kernel/tracing/available_tracers

# 验证追踪器切换
echo function > /sys/kernel/tracing/current_tracer
cat /sys/kernel/tracing/current_tracer

# 验证追踪数据采集
echo 1 > /sys/kernel/tracing/tracing_on
sleep 1
echo 0 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace | head -10

如果上述命令均正常执行,说明 ftrace 基础环境已就绪。下表列出常见问题及解决方案:

现象 可能原因 解决方案
mount: tracefs already mounted tracefs 已挂载 直接使用 /sys/kernel/tracing 即可
available_tracers 只有 nop 内核未开启 CONFIG_FUNCTION_TRACER 重新编译内核,开启相关配置
写入 current_tracer 返回 Invalid argument 追踪器名称错误或不可用 检查 available_tracers 确认正确名称
trace 文件为空 追踪未开启或缓冲区未刷新 确认 tracing_on = 1,且执行了追踪操作
权限不足 非 root 用户操作 使用 sudo 或以 root 身份执行
进阶提示: 在容器环境中,可能需要额外的 --privileged 标志或挂载 /sys/kernel/tracing 卷才能访问 tracefs。对于 Kubernetes 环境,可以通过 securityContext 设置 privileged: true 或添加 SYS_ADMIN 能力。