3. ftrace编译与配置

ftrace 是内核内置的跟踪器,其功能通过内核编译选项(Kconfig)控制。要在目标系统上使用 ftrace,必须在内核编译阶段正确启用相关配置。本章详细讲解关键配置项及其依赖关系,并给出典型配置组合。

3.1 核心配置项:CONFIG_FTRACE

CONFIG_FTRACE 是 ftrace 的总开关。只有启用此项,内核才会编译 ftrace 核心框架。该选项位于内核配置菜单的 Kernel hacking → Tracers 路径下。

配置项 默认值 说明
CONFIG_FTRACE N ftrace 总开关,必须设为 Y 或 M
CONFIG_FUNCTION_TRACER N 启用函数跟踪(function tracer),依赖 CONFIG_FTRACE
CONFIG_FUNCTION_GRAPH_TRACER N 启用函数调用图跟踪(function_graph tracer),依赖 CONFIG_FUNCTION_TRACER
CONFIG_STACKTRACE Y 提供栈回溯支持,多数跟踪器依赖此选项
CONFIG_DYNAMIC_FTRACE N 启用动态 ftrace,允许运行时修改跟踪点,大幅降低性能开销
CONFIG_FTRACE_SYSCALLS N 启用系统调用跟踪点,用于 syscall tracer
提示: 调试驱动时,CONFIG_DYNAMIC_FTRACE 强烈建议开启。它允许在运行时通过 set_ftrace_filter 动态启用/禁用特定函数的跟踪,避免全量跟踪带来的性能冲击。

3.2 配置依赖关系与层级结构

ftrace 的配置项存在严格的依赖链。下图展示了从总开关到具体跟踪器的层级关系。

ftrace 配置依赖层级 CONFIG_FTRACE CONFIG_STACKTRACE CONFIG_FUNCTION_TRACER CONFIG_FTRACE_SYSCALLS CONFIG_FUNCTION_GRAPH_TRACER CONFIG_DYNAMIC_FTRACE 说明:箭头方向表示“依赖”关系。CONFIG_FTRACE 是根,所有跟踪器都依赖它。

3.3 关键配置项详解

3.3.1 CONFIG_FUNCTION_TRACER

启用后,内核会在每个函数的入口插入 mcount(或 fentry)调用。这是 function 和 function_graph 跟踪器的基础。开启此选项会增加内核映像大小约 10%~15%,并引入少量静态性能开销。

3.3.2 CONFIG_DYNAMIC_FTRACE

动态 ftrace 将 mcount 调用点初始化为 nop(空操作)指令。只有在用户通过 debugfs 启用跟踪时,内核才将 nop 替换为实际的跟踪指令。这使未启用跟踪时的性能开销几乎为零。

性能对比:
  • 静态 ftrace(CONFIG_DYNAMIC_FTRACE=N):所有函数始终执行 mcount 调用,即使未启用跟踪,也会引入约 5%~10% 的性能损失。
  • 动态 ftrace(CONFIG_DYNAMIC_FTRACE=Y):未启用跟踪时零开销;启用跟踪后,仅被过滤的函数有开销。

3.3.3 CONFIG_FTRACE_SYSCALLS

启用系统调用跟踪点。驱动调试中,当怀疑系统调用(如 open、ioctl、mmap)行为异常时,此选项可帮助跟踪用户态与内核态的交互边界。

3.4 典型配置组合(驱动调试场景)

以下配置组合适用于大多数驱动调试场景,兼顾功能完整性与性能。

配置项 推荐值 调试用途
CONFIG_FTRACE Y 总开关
CONFIG_FUNCTION_TRACER Y 函数调用跟踪
CONFIG_FUNCTION_GRAPH_TRACER Y 函数调用链路可视化
CONFIG_DYNAMIC_FTRACE Y 运行时按需跟踪,降低开销
CONFIG_STACKTRACE Y 栈回溯支持
CONFIG_FTRACE_SYSCALLS Y 系统调用边界跟踪
CONFIG_FTRACE_EVENTS Y 事件跟踪支持

3.5 配置操作步骤

  1. 进入内核配置界面:
    make menuconfig
  2. 导航到 Tracers 子菜单:
    Kernel hacking  --->
      [*] Tracers  --->
  3. 启用核心选项:
    [*] Enable ftrace - Function Tracer
    [*]   Kernel Function Tracer
    [*]     Kernel Function Graph Tracer
    [*]   Enable/disable function tracing dynamically
    [*]   Trace syscalls
    [*]   Enable trace events
  4. 保存并退出:选择 Save,然后退出配置界面。
  5. 编译内核:
    make -j$(nproc)
    make modules_install
    make install
  6. 验证配置是否生效:
    # 重启后检查 debugfs 挂载点
    mount -t debugfs none /sys/kernel/debug
    ls /sys/kernel/debug/tracing/

    如果看到 available_tracers、current_tracer、set_ftrace_filter 等文件,说明 ftrace 已正确启用。

注意: 嵌入式或生产环境内核可能默认关闭 ftrace。如果目标系统是 Android,需要确认内核是否开启了 CONFIG_ANDROID_LOGGING 相关选项,部分厂商会裁剪 ftrace 以减小内核体积。建议在调试阶段使用自定义编译的内核。

3.6 配置验证:检查 /proc/config.gz

如果目标系统已经运行,可以通过以下命令检查当前内核的 ftrace 配置状态:

# 查看 CONFIG_FTRACE 是否启用
zcat /proc/config.gz | grep CONFIG_FTRACE

# 典型输出示例
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_FTRACE_EVENTS=y

如果 /proc/config.gz 不存在,可以尝试:

cat /boot/config-$(uname -r) | grep CONFIG_FTRACE

3.7 常见配置问题与排查

问题现象 可能原因 解决方案
/sys/kernel/debug/tracing 目录不存在 debugfs 未挂载,或内核未编译 ftrace 执行 mount -t debugfs none /sys/kernel/debug;检查 CONFIG_FTRACE 是否启用
available_tracers 中只有 nop CONFIG_FUNCTION_TRACER 未启用 重新编译内核,启用 CONFIG_FUNCTION_TRACER
启用 function_graph 后系统响应变慢 跟踪了过多函数,或未启用动态 ftrace 使用 set_ftrace_filter 限制跟踪范围;确认 CONFIG_DYNAMIC_FTRACE 已启用
内核编译报错:undefined reference to ftrace 依赖项未正确选择 确保 CONFIG_FTRACE 和 CONFIG_STACKTRACE 同时启用