3. ftrace环境准备
要使用 ftrace 追踪内核调度器行为,首先需要确保 Linux 内核在编译时开启了必要的追踪功能,并且正确挂载了 debugfs 文件系统。本章将详细讲解关键内核配置选项的含义、配置方法以及 debugfs 的挂载步骤。
3.1 核心内核配置选项
ftrace 的功能由一系列内核配置选项(Kconfig)控制。以下表格列出了与调度事件追踪最相关的配置项及其作用:
| 配置选项 | 依赖关系 | 功能描述 | 调度追踪必要性 |
|---|---|---|---|
CONFIG_FTRACE |
无 | ftrace 框架的总开关,必须开启 | 必需 |
CONFIG_FUNCTION_TRACER |
CONFIG_FTRACE | 启用函数级追踪,可记录内核函数的调用入口和返回 | 必需(追踪调度函数入口) |
CONFIG_FUNCTION_GRAPH_TRACER |
CONFIG_FUNCTION_TRACER | 以调用图形式显示函数执行流程,包含子函数耗时 | 推荐(分析调度延迟) |
CONFIG_SCHED_TRACER |
CONFIG_FTRACE | 启用调度器专用追踪器,记录进程切换、唤醒、迁移等事件 | 必需 |
CONFIG_FTRACE_SYSCALLS |
CONFIG_FTRACE | 支持追踪系统调用入口和退出 | 推荐(关联调度与系统调用) |
CONFIG_DYNAMIC_FTRACE |
CONFIG_FUNCTION_TRACER | 动态插桩,允许运行时选择追踪哪些函数,减少性能开销 | 必需(生产环境必备) |
CONFIG_STACK_TRACER |
CONFIG_FTRACE | 记录内核栈使用情况,辅助分析栈溢出 | 可选 |
CONFIG_FTRACE、CONFIG_FUNCTION_TRACER、CONFIG_SCHED_TRACER 和 CONFIG_DYNAMIC_FTRACE。如果内核版本较新(5.x+),CONFIG_SCHED_TRACER 可能已被拆分为更细粒度的 tracepoint,但仍需确保相关选项被选中。
3.2 配置选项的依赖关系
内核配置选项之间存在严格的依赖树。下图展示了 ftrace 核心选项的依赖关系,帮助理解哪些选项是必须手动开启的:
3.3 检查与配置内核选项
在现有系统上,可以通过以下方法检查当前内核是否已开启所需选项:
- 查看 /proc/config.gz(如果内核编译时开启了
CONFIG_IKCONFIG_PROC):
zcat /proc/config.gz | grep -E "CONFIG_FTRACE|CONFIG_FUNCTION_TRACER|CONFIG_SCHED_TRACER"
- 查看 /boot/config-$(uname -r):
grep -E "CONFIG_FTRACE|CONFIG_FUNCTION_TRACER|CONFIG_SCHED_TRACER" /boot/config-$(uname -r)
- 使用 /sys 文件系统(如果内核已运行且 debugfs 已挂载):
ls /sys/kernel/tracing/available_tracers # 查看可用的追踪器列表
如果输出中包含 function、function_graph、sched_switch 等,说明对应功能已启用。
CONFIG_DYNAMIC_FTRACE)以减少追踪对系统性能的影响。重新编译内核时,可以通过 make menuconfig 进入 Kernel hacking → Tracers 菜单进行配置。
3.4 挂载 debugfs 文件系统
ftrace 的用户空间接口通过 debugfs 文件系统暴露。在大多数现代 Linux 发行版中,debugfs 默认挂载在 /sys/kernel/debug 路径下,而 ftrace 的控制文件则位于 /sys/kernel/debug/tracing(或 /sys/kernel/tracing,取决于内核版本)。
3.4.1 手动挂载 debugfs
如果系统未自动挂载,可以手动执行以下命令:
# 挂载 debugfs 到 /sys/kernel/debug
mount -t debugfs none /sys/kernel/debug
# 验证挂载是否成功
mount | grep debugfs
挂载成功后,ftrace 的控制目录结构如下:
/sys/kernel/debug/tracing/
├── available_tracers # 列出当前内核支持的追踪器
├── current_tracer # 当前激活的追踪器
├── tracing_on # 追踪开关(1=开启,0=关闭)
├── trace # 追踪结果(人类可读格式)
├── trace_pipe # 追踪结果(流式输出)
├── set_ftrace_filter # 函数过滤器(白名单)
├── set_ftrace_notrace # 函数过滤器(黑名单)
├── events/ # 事件追踪子系统目录
│ ├── sched/ # 调度器事件(sched_switch, sched_wakeup 等)
│ └── ...
└── per_cpu/ # 每个 CPU 的追踪缓冲区
3.4.2 开机自动挂载
为了确保每次系统启动时 debugfs 自动挂载,可以将以下配置添加到 /etc/fstab 文件中:
# 在 /etc/fstab 末尾添加一行
debugfs /sys/kernel/debug debugfs defaults 0 0
或者使用 systemd 的挂载单元(适用于 systemd 系统):
# 创建挂载单元文件
cat <<EOF | sudo tee /etc/systemd/system/sys-kernel-debug.mount
[Unit]
Description=Debug File System
DefaultDependencies=no
[Mount]
What=debugfs
Where=/sys/kernel/debug
Type=debugfs
[Install]
WantedBy=sysinit.target
EOF
# 启用并启动
systemctl enable sys-kernel-debug.mount
systemctl start sys-kernel-debug.mount
3.5 验证 ftrace 环境
完成配置和挂载后,通过以下步骤验证环境是否准备就绪:
- 检查 debugfs 挂载点:
ls /sys/kernel/debug/tracing/
- 查看可用的追踪器:
cat /sys/kernel/debug/tracing/available_tracers
预期输出应包含 function、function_graph、sched_switch、wakeup、wakeup_dl 等。
- 查看可用的调度事件:
ls /sys/kernel/debug/tracing/events/sched/
预期输出应包含 sched_switch、sched_wakeup、sched_wakeup_new、sched_migrate_task 等事件目录。
- 快速测试追踪功能:
# 开启追踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 执行一些操作(如 ls 命令)
ls /tmp
# 关闭追踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 查看追踪结果
cat /sys/kernel/debug/tracing/trace | head -20
如果看到类似以下输出,说明 ftrace 环境已正常工作:
# tracer: nop
#
# entries-in-buffer/entries-written: 142/142 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
bash-1234 [000] .... 1234.567890: sched_switch: prev_comm=bash prev_pid=1234 prev_prio=120 prev_state=R ==> next_comm=swapper/0 next_pid=0 next_prio=120
3.6 常见问题与排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
mount: /sys/kernel/debug: debugfs already mounted |
debugfs 已被系统自动挂载 | 无需操作,直接使用 /sys/kernel/debug/tracing |
cat: /sys/kernel/debug/tracing/available_tracers: No such file or directory |
debugfs 未挂载或内核未开启 ftrace | 先执行 mount -t debugfs none /sys/kernel/debug,再检查内核配置 |
available_tracers 中只有 nop |
内核未开启 CONFIG_FUNCTION_TRACER 或 CONFIG_SCHED_TRACER |
重新编译内核,开启相应选项 |
events/sched/ 目录为空 |
内核未开启调度事件追踪 | 检查 CONFIG_SCHED_TRACER 或 CONFIG_EVENT_TRACING |
| 追踪结果中无调度事件 | 未启用调度事件或过滤器设置不当 | 执行 echo 1 > /sys/kernel/debug/tracing/events/sched/enable |
- ✅ 内核配置:
CONFIG_FTRACE=y、CONFIG_FUNCTION_TRACER=y、CONFIG_SCHED_TRACER=y、CONFIG_DYNAMIC_FTRACE=y - ✅ debugfs 挂载:
mount | grep debugfs有输出 - ✅ ftrace 目录存在:
ls /sys/kernel/debug/tracing/有内容 - ✅ 调度事件可用:
ls /sys/kernel/debug/tracing/events/sched/包含sched_switch等 - ✅ 快速测试通过:
cat /sys/kernel/debug/tracing/trace能输出追踪记录