3、环境准备:编译内核开启Ftrace选项,挂载tracefs,检查当前系统支持情况

好,咱们正式开始动手了。

这一节说白了就是搭环境。你别小看这一步,我见过太多人兴致勃勃学Ftrace,结果第一步就卡住了——要么内核没开编译选项,要么tracefs没挂上,折腾半天连个基本功能都跑不起来。

我个人习惯,在开始任何内核追踪工作之前,先花10分钟把环境确认清楚。这10分钟花得值,后面能省下大把排查时间。

3.1 检查当前内核是否支持Ftrace

先别急着编译内核。咱们先看看你手头的系统支不支持。

最简单的办法,就是看看有没有 /sys/kernel/tracing 这个目录。或者老一点的系统,可能是 /sys/kernel/debug/tracing

ls /sys/kernel/tracing

如果能看到一堆文件和子目录,比如 available_tracerscurrent_tracer 这些,那恭喜你,系统已经支持了。

再看看有哪些可用的tracer:

cat /sys/kernel/tracing/available_tracers

输出大概长这样:

function_graph function nop

嗯,这里要注意。如果只有 nop,那说明内核虽然编译了Ftrace框架,但没开具体的追踪器。这种情况我遇到过,当时还纳闷了半天,后来发现是发行版内核为了省空间,把function tracer给关了。

注意: 如果 available_tracers 里只有 nop,说明你的内核没有开启Ftrace的完整功能。需要重新编译内核。

3.2 编译内核开启Ftrace选项

好,如果你需要自己编译内核,那咱们一步步来。

我建议你用最新的长期支持版内核,比如6.x系列。别用太老的,有些选项位置不一样,容易搞混。

3.2.1 获取内核源码

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
tar -xf linux-6.1.tar.xz
cd linux-6.1

3.2.2 配置内核选项

运行配置界面:

make menuconfig

然后按以下路径开启关键选项:

配置路径 选项名 说明
Kernel hacking → Tracers CONFIG_FTRACE Ftrace主开关,必须开启
Kernel hacking → Tracers CONFIG_FUNCTION_TRACER 函数级追踪,最常用
Kernel hacking → Tracers CONFIG_FUNCTION_GRAPH_TRACER 函数调用图,看调用链必备
Kernel hacking → Tracers CONFIG_STACK_TRACER 栈回溯,排查死锁时有用
Kernel hacking → Tracers CONFIG_DYNAMIC_FTRACE 动态插桩,减少性能开销
Kernel hacking → Tracers CONFIG_FTRACE_SYSCALLS 系统调用追踪,性能分析常用
我的经验: 如果你不确定开哪些,就把 Tracers 菜单下的选项全开了。反正编译一次,后面省事。我刚开始学的时候只开了最基本的,结果想用某个功能发现没开,又得重新编译,浪费时间。

3.2.3 编译并安装

make -j$(nproc)
make modules_install
make install

重启后选择新内核。验证一下:

uname -r
cat /proc/config.gz | gunzip | grep CONFIG_FTRACE

如果看到 CONFIG_FTRACE=y,那就成了。

3.3 挂载tracefs

内核编译好了,但Ftrace的文件系统还没挂上。tracefs是专门给Ftrace用的虚拟文件系统。

现代内核通常会自动挂载。但有时候发行版没配好,就得手动来。

mount -t tracefs tracefs /sys/kernel/tracing

如果你用的是老内核,路径可能是 /sys/kernel/debug/tracing,那就得先挂debugfs:

mount -t debugfs debugfs /sys/kernel/debug

我个人建议直接挂tracefs,别走debugfs那条路。debugfs是给所有调试功能用的,权限管理比较粗,tracefs更专一,也更安全。

验证挂载是否成功:

mount | grep tracefs

输出应该类似:

tracefs on /sys/kernel/tracing type tracefs (rw,relatime)

3.4 检查当前系统支持情况

环境搭好了,咱们做个全面体检。

3.4.1 检查tracer列表

cat /sys/kernel/tracing/available_tracers

理想输出:

function_graph function nop

如果有 function_graph,说明你可以看到函数的调用关系图。这个在分析调度延迟时特别好用。

3.4.2 检查追踪事件

ls /sys/kernel/tracing/events/sched/

你会看到一堆调度相关的事件,比如:

  • sched_switch — 进程切换
  • sched_wakeup — 进程被唤醒
  • sched_migrate_task — 任务迁移
  • sched_process_exec — 进程执行

这些事件是咱们分析调度性能的核心素材。

3.4.3 检查当前追踪状态

cat /sys/kernel/tracing/current_tracer
cat /sys/kernel/tracing/tracing_on

current_tracer 显示当前使用的追踪器,默认是 nop
tracing_on 显示是否正在追踪,1表示开启,0表示关闭。

快速验证: 你可以试着开启function tracer,看看能不能抓到数据。
echo function > /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 -20
如果能看到一堆函数调用记录,说明环境完全OK。

3.5 常见问题与避坑

我把自己踩过的坑列出来,你遇到了直接对照着查:

  • Permission denied — 大部分Ftrace文件需要root权限。用 sudo 或者切到root用户。
  • tracefs挂不上 — 检查内核是否编译了 CONFIG_TRACEFS。没开的话重新编译。
  • available_tracers只有nop — 内核没开 CONFIG_FUNCTION_TRACER。回去重新配置。
  • trace文件为空 — 检查 tracing_on 是不是1,或者 current_tracer 是不是 nop

我曾经在一个嵌入式板子上折腾了整整一下午,就是因为内核编译时忘了开 CONFIG_DYNAMIC_FTRACE。结果每次追踪都卡得要死,还以为是板子性能不行。后来才发现是静态插桩把所有函数都hook了,性能开销巨大。所以,动态Ftrace一定要开

3.6 小结

环境准备就这些。说白了就是三步:

  1. 检查现有内核是否支持
  2. 不支持就编译新内核,开齐Ftrace选项
  3. 挂载tracefs,验证可用性

做完这些,你的系统就准备好迎接Ftrace的各种玩法了。下一节咱们开始真正上手,用Ftrace抓调度延迟数据。