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 的配置项存在严格的依赖链。下图展示了从总开关到具体跟踪器的层级关系。
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 配置操作步骤
- 进入内核配置界面:
make menuconfig - 导航到 Tracers 子菜单:
Kernel hacking ---> [*] Tracers ---> - 启用核心选项:
[*] Enable ftrace - Function Tracer [*] Kernel Function Tracer [*] Kernel Function Graph Tracer [*] Enable/disable function tracing dynamically [*] Trace syscalls [*] Enable trace events - 保存并退出:选择
Save,然后退出配置界面。 - 编译内核:
make -j$(nproc) make modules_install make install - 验证配置是否生效:
# 重启后检查 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 同时启用 |