Appearance
ftrace机制详解
ftrace(Function Tracer)是Linux内核内置的强大函数跟踪工具,它能够帮助开发者深入了解内核函数的执行流程、性能瓶颈以及系统行为。ftrace从Linux 2.6.27版本开始引入,已经成为内核开发和调试的重要工具。
基本概念和架构
ftrace基于内核的函数入口和出口钩子机制,通过在编译时插入代码来实现跟踪功能。它的主要组件包括:
- 跟踪器(Tracers):不同类型的跟踪器用于不同的分析目的
- 跟踪缓冲区:存储跟踪数据的环形缓冲区
- 过滤器:用于筛选特定的函数或事件
- 输出格式:多种数据输出格式供分析使用
启用和配置ftrace
在使用ftrace之前,需要确保内核已启用相关配置选项:
bash
# 检查内核配置
zcat /proc/config.gz | grep CONFIG_FTRACE
# 或者
grep CONFIG_FTRACE /boot/config-$(uname -r)
# 应该看到以下配置项已启用:
# CONFIG_FTRACE=y
# CONFIG_FUNCTION_TRACER=y
# CONFIG_FUNCTION_GRAPH_TRACER=y
# CONFIG_STACK_TRACER=yftrace的主要接口位于/sys/kernel/debug/tracing/目录下:
bash
# 检查ftrace是否可用
ls /sys/kernel/debug/tracing/
# 常用文件:
# available_tracers - 可用的跟踪器列表
# current_tracer - 当前使用的跟踪器
# trace - 跟踪输出
# tracing_on - 跟踪开关
# trace_options - 跟踪选项
# set_ftrace_filter - 函数过滤器
# set_ftrace_notrace - 排除函数列表主要跟踪器类型
1. Function Tracer
记录函数调用信息,显示函数名和时间戳:
bash
# 启用function跟踪器
echo function > /sys/kernel/debug/tracing/current_tracer
# 开始跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 执行一些操作...
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 查看结果
cat /sys/kernel/debug/tracing/trace输出示例:
# tracer: function
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
bash-1234 [001] .... 12345.678901: sys_openat <-SyS_openat
bash-1234 [001] .... 12345.678902: vfs_open <-do_dentry_open
bash-1234 [001] .... 12345.678903: do_dentry_open <-path_openat2. Function Graph Tracer
以函数调用图的形式显示函数执行流程:
bash
# 启用function_graph跟踪器
echo function_graph > /sys/kernel/debug/tracing/current_tracer
# 设置最大图形深度(可选)
echo 3 > /sys/kernel/debug/tracing/max_graph_depth
# 开始跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 执行操作...
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 查看结果
cat /sys/kernel/debug/tracing/trace输出示例:
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
1) | sys_openat() {
1) | do_sys_open() {
1) 0.123 us | getname();
1) 0.456 us | path_openat();
1) | fd_install() {
1) 0.789 us | __fd_install();
1) 1.234 us | }
1) 3.456 us | }
1) 4.567 us | }3._NOP Tracer
默认跟踪器,不产生任何跟踪数据,仅用于事件跟踪:
bash
# 切换到nop跟踪器
echo nop > /sys/kernel/debug/tracing/current_tracer事件跟踪
除了函数跟踪,ftrace还支持事件跟踪,可以跟踪内核中的各种事件:
bash
# 查看可用事件
ls /sys/kernel/debug/tracing/events/
# 启用特定事件
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
# 启用所有sched事件
echo 1 > /sys/kernel/debug/tracing/events/sched/enable
# 查看跟踪结果
cat /sys/kernel/debug/tracing/trace过滤和限制
函数过滤
bash
# 只跟踪特定函数
echo 'vfs_*' > /sys/kernel/debug/tracing/set_ftrace_filter
# 排除特定函数
echo 'vfs_read*' > /sys/kernel/debug/tracing/set_ftrace_notrace
# 清除过滤器
echo > /sys/kernel/debug/tracing/set_ftrace_filter
echo > /sys/kernel/debug/tracing/set_ftrace_notracePID过滤
bash
# 只跟踪特定进程
echo 1234 > /sys/kernel/debug/tracing/set_ftrace_pid
# 清除PID过滤
echo > /sys/kernel/debug/tracing/set_ftrace_pid高级使用技巧
1. 实时跟踪
bash
# 实时查看跟踪结果
while true; do
cat /sys/kernel/debug/tracing/trace_pipe
sleep 1
done2. 跟踪特定时间段
bash
# 记录跟踪开始前的时间戳
cat /sys/kernel/debug/tracing/trace_marker
# 执行操作...
# 再次记录时间戳
echo "Operation completed" > /sys/kernel/debug/tracing/trace_marker
# 分析两个标记之间的数据3. 自定义跟踪标记
bash
# 在代码中添加自定义标记
echo "Starting critical section" > /sys/kernel/debug/tracing/trace_marker
# 执行关键操作
echo "Ending critical section" > /sys/kernel/debug/tracing/trace_marker实战案例
案例1:分析系统启动性能
bash
#!/bin/bash
# 分析系统启动过程中函数调用情况
# 清除之前的跟踪数据
echo > /sys/kernel/debug/tracing/trace
# 设置跟踪器
echo function_graph > /sys/kernel/debug/tracing/current_tracer
# 设置过滤器,只关注初始化相关函数
echo '*init*' > /sys/kernel/debug/tracing/set_ftrace_filter
# 开始跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 等待一段时间让系统稳定
sleep 10
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 保存结果
cp /sys/kernel/debug/tracing/trace /tmp/boot_trace.txt
# 清除过滤器
echo > /sys/kernel/debug/tracing/set_ftrace_filter案例2:诊断调度延迟
bash
#!/bin/bash
# 诊断进程调度延迟问题
# 启用调度事件跟踪
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
# 设置跟踪选项,显示任务优先级
echo print-parent > /sys/kernel/debug/tracing/trace_options
# 开始跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 运行有问题的应用程序
./problematic_app
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 分析调度切换情况
cat /sys/kernel/debug/tracing/trace | grep sched_switch > /tmp/sched_analysis.txt
# 禁用事件跟踪
echo 0 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable案例3:跟踪中断处理
bash
#!/bin/bash
# 跟踪中断处理函数执行情况
# 启用irq事件跟踪
echo 1 > /sys/kernel/debug/tracing/events/irq/enable
# 启用软中断跟踪
echo 1 > /sys/kernel/debug/tracing/events/softirq/enable
# 设置function_graph跟踪器
echo function_graph > /sys/kernel/debug/tracing/current_tracer
# 开始跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 触发中断(例如网络流量)
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 查看结果
cat /sys/kernel/debug/tracing/trace > /tmp/irq_trace.txt
# 禁用事件跟踪
echo 0 > /sys/kernel/debug/tracing/events/irq/enable
echo 0 > /sys/kernel/debug/tracing/events/softirq/enable性能分析技巧
1. 查找热点函数
bash
# 启用function跟踪器并收集数据
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 运行测试负载...
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 统计函数调用次数
awk '{print $NF}' /sys/kernel/debug/tracing/trace | sort | uniq -c | sort -nr | head -202. 分析函数执行时间
bash
# 使用function_graph跟踪器
echo function_graph > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 运行测试...
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 提取执行时间数据
awk '/^[[:space:]]*[0-9]/ {print $3, $NF}' /sys/kernel/debug/tracing/trace | \
sort -k1 -hr | head -20最佳实践
- 谨慎使用:ftrace会产生额外开销,生产环境中应谨慎使用
- 及时关闭:跟踪完成后及时关闭跟踪器,避免影响系统性能
- 合理过滤:使用过滤器减少无关数据,提高分析效率
- 定期清理:定期清理跟踪缓冲区,避免数据溢出
- 安全考虑:debugfs通常只有root权限才能访问
常见问题解决
问题1:无法访问tracing目录
bash
# 挂载debugfs
mount -t debugfs none /sys/kernel/debug
# 或者添加到/etc/fstab中自动挂载
echo "none /sys/kernel/debug debugfs defaults 0 0" >> /etc/fstab问题2:跟踪数据为空
bash
# 检查跟踪开关
cat /sys/kernel/debug/tracing/tracing_on
# 确认跟踪器设置
cat /sys/kernel/debug/tracing/current_tracer
# 检查过滤器设置
cat /sys/kernel/debug/tracing/set_ftrace_filter问题3:跟踪影响系统性能
bash
# 使用更轻量的跟踪器
echo nop > /sys/kernel/debug/tracing/current_tracer
# 或者减少跟踪范围
echo 'specific_function' > /sys/kernel/debug/tracing/set_ftrace_filter通过掌握ftrace的使用方法,你可以深入分析Linux内核的行为,诊断性能问题,并优化系统性能。