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 核心选项的依赖关系,帮助理解哪些选项是必须手动开启的:

ftrace 内核配置依赖关系图 CONFIG_FTRACE CONFIG_FUNCTION_TRACER CONFIG_SCHED_TRACER CONFIG_FTRACE_SYSCALLS CONFIG_FUNCTION_GRAPH_TRACER CONFIG_DYNAMIC_FTRACE CONFIG_STACK_TRACER 说明: 箭头表示“依赖”关系,即下层选项需要上层选项开启后才能生效。 绿色节点为调度追踪的必需项,橙色节点为强烈推荐项,紫色节点为可选项。

3.3 检查与配置内核选项

在现有系统上,可以通过以下方法检查当前内核是否已开启所需选项:

  1. 查看 /proc/config.gz(如果内核编译时开启了 CONFIG_IKCONFIG_PROC):
zcat /proc/config.gz | grep -E "CONFIG_FTRACE|CONFIG_FUNCTION_TRACER|CONFIG_SCHED_TRACER"
  1. 查看 /boot/config-$(uname -r):
grep -E "CONFIG_FTRACE|CONFIG_FUNCTION_TRACER|CONFIG_SCHED_TRACER" /boot/config-$(uname -r)
  1. 使用 /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 环境

完成配置和挂载后,通过以下步骤验证环境是否准备就绪:

  1. 检查 debugfs 挂载点:
ls /sys/kernel/debug/tracing/
  1. 查看可用的追踪器:
cat /sys/kernel/debug/tracing/available_tracers

预期输出应包含 function、function_graph、sched_switch、wakeup、wakeup_dl 等。

  1. 查看可用的调度事件:
ls /sys/kernel/debug/tracing/events/sched/

预期输出应包含 sched_switch、sched_wakeup、sched_wakeup_new、sched_migrate_task 等事件目录。

  1. 快速测试追踪功能:
# 开启追踪
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 能输出追踪记录