3、环境准备:编译内核开启Ftrace选项,挂载tracefs,检查当前系统支持情况
好,咱们正式开始动手了。
这一节说白了就是搭环境。你别小看这一步,我见过太多人兴致勃勃学Ftrace,结果第一步就卡住了——要么内核没开编译选项,要么tracefs没挂上,折腾半天连个基本功能都跑不起来。
我个人习惯,在开始任何内核追踪工作之前,先花10分钟把环境确认清楚。这10分钟花得值,后面能省下大把排查时间。
3.1 检查当前内核是否支持Ftrace
先别急着编译内核。咱们先看看你手头的系统支不支持。
最简单的办法,就是看看有没有 /sys/kernel/tracing 这个目录。或者老一点的系统,可能是 /sys/kernel/debug/tracing。
ls /sys/kernel/tracing
如果能看到一堆文件和子目录,比如 available_tracers、current_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 | 系统调用追踪,性能分析常用 |
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表示关闭。
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 小结
环境准备就这些。说白了就是三步:
- 检查现有内核是否支持
- 不支持就编译新内核,开齐Ftrace选项
- 挂载tracefs,验证可用性
做完这些,你的系统就准备好迎接Ftrace的各种玩法了。下一节咱们开始真正上手,用Ftrace抓调度延迟数据。