Linux内核调试实战:用ftrace和trace-cmd追踪CPU热插拔与电源管理事件

1. 内核事件追踪技术概述

在Linux系统开发中,电源管理问题往往是最难调试的痛点之一。当系统出现suspend/resume异常或CPU热插拔问题时,传统的printk调试方式不仅效率低下,还可能因为添加调试语句而改变问题发生的时序。这时,动态追踪技术就成为了我们的"终极武器"。

ftrace作为Linux内核内置的追踪框架,具有零开销、无侵入的特点。它通过特殊的ring buffer记录内核函数调用、事件触发等信息,配合trace-cmd工具集,我们可以轻松捕获:

  • CPU热插拔全过程(_cpu_down/cpu_die调用链)
  • suspend/resume关键路径(trace_suspend_resume事件)
  • CPU idle循环行为(cpu_startup_entry调用)
  • 电源管理接口调用(PSCI操作时序)

与静态代码分析相比,动态追踪能真实反映系统运行时行为,特别适合解决那些"只在特定条件下出现"的电源管理问题。

2. 环境准备与基础配置

2.1 内核配置要求

确保内核已启用以下配置选项:

CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_TRACING=y
CONFIG_EVENT_TRACING=y
CONFIG_DEBUG_FS=y

2.2 挂载debugfs文件系统

mount -t debugfs none /sys/kernel/debug

2.3 安装trace-cmd工具

# Ubuntu/Debian
sudo apt install trace-cmd

# RHEL/CentOS
sudo yum install trace-cmd

2.4 常用ftrace接口路径

/sys/kernel/debug/tracing/tracing_on
/sys/kernel/debug/tracing/current_tracer
/sys/kernel/debug/tracing/trace
/sys/kernel/debug/tracing/set_event

3. CPU热插拔事件追踪实战

3.1 捕获CPU离线全过程

当我们需要分析CPU离线异常时,可以记录从用户空间触发到最终CPU下电的完整调用链:

# 设置追踪事件
echo 1 > /sys/kernel/debug/tracing/events/cpuhp/enable
echo 1 > /sys/kernel/debug/tracing/events/ipi/enable

# 开始记录
echo 1 > /sys/kernel/debug/tracing/tracing_on

# 触发CPU离线(示例中下线CPU1)
echo 0 > /sys/devices/system/cpu/cpu1/online

# 停止记录
echo 0 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace > cpu_offline.log

关键事件序列通常包括:

  1. cpu_down - 用户空间触发热插拔操作
  2. _cpu_down - 核心下线逻辑开始
  3. cpuhp/CPU_DEAD - CPU死亡通知
  4. cpu_die - 架构相关下线操作
  5. PSCI接口调用 - 实际硬件下电

3.2 使用trace-cmd进行高级捕获

trace-cmd提供了更友好的命令行接口:

trace-cmd record -e cpuhp -e ipi \
    -p function_graph -l '_cpu_down' -l 'cpu_die' \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu1/online"

生成的报告会清晰显示:

  • 各阶段耗时统计
  • 函数调用关系图
  • 跨CPU事件时序

注意:当追踪CPU热插拔时,建议避免下线所有非boot CPU,否则可能导致系统无响应。

4. Suspend/Resume事件深度分析

4.1 电源管理关键事件追踪

Linux内核定义了专门的电源管理追踪点:

# 查看所有suspend/resume相关事件
grep suspend /sys/kernel/debug/tracing/available_events

# 常用事件包括:
# power:suspend_resume
# power:cpu_idle
# power:cpu_frequency

完整捕获一次系统挂起流程:

trace-cmd record \
    -e power:suspend_resume \
    -e power:cpu_idle \
    -l psci_system_suspend_enter \
    -l cpu_suspend \
    echo mem > /sys/power/state

4.2 关键路径解析

典型的suspend/resume追踪报告会显示以下关键阶段:

  1. Suspend准备阶段 :

    • suspend_enter 调用开始
    • 非boot CPU下线( disable_nonboot_cpus )
    • 设备级suspend回调
  2. 核心suspend阶段 :

    • psci_system_suspend_enter 调用
    • CPU上下文保存( __cpu_suspend_enter )
    • PSCI接口调用
  3. Resume恢复阶段 :

    • boot CPU恢复( cpu_resume )
    • 非boot CPU重新上线
    • 设备resume回调

4.3 常见问题定位技巧

通过分析追踪报告,可以快速定位:

  • suspend卡住 :检查最后记录的函数调用
  • resume失败 :对比suspend/resume的对称操作
  • CPU无法唤醒 :确认PSCI返回值和唤醒源
  • 性能问题 :测量各阶段耗时,识别瓶颈

5. 高级技巧与实战案例

5.1 函数图追踪(function_graph)

当需要分析特定函数的内部调用关系时:

# 追踪cpu_die及其子调用
trace-cmd record -p function_graph -g cpu_die \
    -l psci_cpu_off \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu1/online"

典型输出示例:

cpu_die() {
  psci_cpu_off() {
    invoke_psci_fn() {
      __invoke_psci_fn_smc();
    }
  }
}

5.2 过滤特定CPU事件

在多核环境下,可以只关注特定CPU的事件:

# 只记录CPU1的事件
trace-cmd record -e cpuhp -C 1 \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu1/online"

5.3 实际案例:CPU热插拔超时

某次调试中,发现CPU下线操作偶尔会超时。通过以下命令捕获问题:

trace-cmd record -e cpuhp -l '_cpu_down' -l 'cpu_die' \
    -e irq:irq_handler_entry \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu1/online"

分析报告发现,在 _cpu_down 和 cpu_die 之间有异常的IRQ处理延迟,最终定位到某个驱动没有正确处理hotplug通知。

6. 工具链集成与自动化

6.1 脚本化追踪方案

将常用追踪场景封装为脚本:

#!/bin/bash
# trace_cpu_hotplug.sh

CPU=$1
EVENTS="cpuhp:*,ipi:*"
FUNCS="_cpu_down,cpu_die,cpu_psci_cpu_die"

trace-cmd record -e $EVENTS -l $FUNCS \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu$CPU/online"
trace-cmd report -l > trace_report.txt

6.2 与perf集成分析

结合perf进行更全面的性能分析:

perf probe -a '_cpu_down'
perf probe -a 'cpu_die'
perf stat -e 'probe:_cpu_down' -e 'probe:cpu_die' \
    bash -c "echo 0 > /sys/devices/system/cpu/cpu1/online"

6.3 持久化追踪配置

保存常用过滤器配置:

# 电源管理事件过滤器
echo 'power:suspend_resume power:cpu_idle' > /sys/kernel/debug/tracing/set_event

# 函数过滤器
echo '_cpu_down cpu_die psci_*' > /sys/kernel/debug/tracing/set_ftrace_filter

# 保存配置
cp /sys/kernel/debug/tracing/saved_cmdlines /etc/trace_cmdlines
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐