点击上方“Linux随笔录”,选择“置顶/星标公众号”
福利干货,第一时间送达
- 前言
- 环境
- ftrace背景
- ftrace优势
- ftrace的配置与traceing目录介绍
- 内核下ftrace配置详解
- 挂载debugfs文件系统
- traceing目录介绍
- ftrace使用
function跟踪器
function_graph跟踪器
trace-cmd引入
安装trace-cmd
trace-cmd常见命令
trace-cmd使用流程
trace-cmd使用
总结
前言
之前几篇我们有学习过Linux内核调试技术手段
Linux内核调试 | BUG_ON与WARN_ON与dump_stack的使用
那如果要判断内核函数是否执行和调用关系我们知道要用printk
或者dump_stack
来验证。不过这种方法的有些方法需要每次编译烧录工作效率过低,那没有效率高的方法,答案是有的!Linux内核里提供了一些调试追踪的工具如ftrace
,kprobe
,uprobe
,eBPF
,perf
,SystemTap
等。其中最常用且方便的是ftrace
, 那么本篇来讲下Linux性能工具ftrace
的使用
环境
硬件平台:飞凌OK3588开发板
内核源码:5.10.66-rt53
编译环境:Ubuntu 20.04 LTS
编译工具链:aarch64-linux-gnu-
ftrace背景
ftrace
是 Linux 内核中的一个功能强大的跟踪框架,用于分析和调试内核性能。它允许开发者以多种方式跟踪内核函数的调用、记录函数的执行时间、分析系统性能瓶颈并进行系统调优等。ftrace
提供了一个灵活的接口,可以通过它来启用或禁用跟踪功能,收集和查看跟踪数据。
ftrace优势
- 灵活性:
ftrace
可以跟踪内核中的几乎所有函数调用,并允许用户选择他们希望跟踪的特定函数。 - 低开销:与其他跟踪工具相比,
ftrace
的开销较小,因此适合在生产环境中使用。 - 多种跟踪方式:
- 函数跟踪:跟踪函数的进入和退出。
- 事件跟踪:可以跟踪特定的内核事件(如调度、I/O 操作等)。
- 性能分析:收集执行时间、调用频率等信息,帮助分析性能问题。
- 可视化工具:通过
trace-cmd
和perf
等工具,用户可以将ftrace
收集的数据可视化,以帮助分析。 - 动态跟踪:支持动态启用和禁用跟踪,而无需重新编译内核。
ftrace的配置与traceing目录介绍
内核下ftrace配置详解
# 体系结构相关的实现
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
# Function Trace
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_DYNAMIC_FTRACE=y # 打开DYANMIC_FTRACE后性能开销可忽略
# 各种tracer的支持
CONFIG_GENERIC_TRACER=y
CONFIG_NOP_TRACER=y
CONFIG_STACK_TRACER=y
CONFIG_IRQSOFF_TRACER=y
CONFIG_PREEMPT_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_TRACER_SNAPSHOT=y
CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
# 静态Trace events
CONFIG_TRACEPOINTS=y
CONFIG_EVENT_TRACING=y
CONFIG_TRACING_SUPPORT=y
CONFIG_TRACING=y
# 动态Trace events
CONFIG_PROBE_EVENTS=y
CONFIG_KPROBE_EVENTS=y
CONFIG_UPROBE_EVENTS=y
# 其它相关配置
CONFIG_TRACE_CLOCK=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_STACKTRACE=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_TRACE_IRQFLAGS=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_TRACER_MAX_TRACE=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_BLK_DEV_IO_TRACE=y
挂载debugfs文件系统
ftrace
是基于 debugfs
调试文件系统的,所以我们的第一步就是先挂载debugfs
mount -t debugfs none /sys/kernel/debug
或者将如下内容添加到/etc/fstab文件:
debugfs /sys/kernel/debug debugfs defaults 0 0
我们就可以在 /sys/kernel/debug/tracing
目录下看到有关trace
节点信息,这是ftrace
实现了一个tracefs
的内存文件系统
traceing目录介绍
traceing目录下的节点如下图所示
看起来挺多的,下面我只讲常用的节点信息,大家想了解更多可以看下README文件,里面详解了各个属性文件的含义。
tracing_on
- 描述:这个文件用于启用或禁用跟踪。如果设置为
1
,则启用跟踪;设置为0
则禁用。 - 例子:
echo 1 > tracing_on # 启用跟踪
echo 0 > tracing_on # 禁用跟踪
trace
- 描述:这个文件包含当前的跟踪记录。读取此文件可以查看所有收集到的跟踪信息。
- 例子:
cat trace # 查看跟踪记录
echo > trace # 清空跟踪记录
current_tracer
- 描述:这个文件包含当前启用的
tracer
- 例子:
cat current_tracer
function #当前用function的trace
available_tracers
- 描述:这个文件包含当前支持的追踪器类型
- 例子:
cat available_tracers # 查看当前支持的追踪器类型
blk function_graph function nop
- nop:表示为空,不追踪
- function:函数调用跟踪器来跟踪函数的执行
- function_graph:与函数跟踪器类似, 函数图形跟踪器跟踪函数的进入和退出。 然后它提供了绘制类似于C代码源的函数调用图的能力。
- blk: 块跟踪器。 blktrace用户应用程序使用的跟踪器。
其中我用的比较多的是function_graph
available_filter_functions
- 描述:这列出了
ftrace
可以处理并可跟踪的函数
cat available_filter_functions | grep "ip_rcv" # 搜索ip_rcv函数是否存在
set_ftrace_filter
- 描述:过滤函数追踪,仅仅追踪写入该文件的函数名。可填入的参数,可以通过
available_filter_functions
文件查看当前支持的函数名 - 例子:
# 将ip_rcv加入过滤列表
echo ip_rcv > set_ftrace_filter
注意:如果写入的参数不是 available_filter_functions
文件里,就会报无效参数写入
echo open > set_ftrace_filter
-bash: echo: write error: Invalid argument
set_graph_function
- 描述:过滤函数追踪,仅仅追踪写入该文件的函数名。可填入的参数,可以通过
available_filter_functions
文件查看当前支持的函数名
set_graph_function
通常与 function_graph
跟踪器一起使用
set_ftrace_pid
- 描述: 是否系统对
set_ftrace_pid
对指定的PID进程进行追踪。 - 例子:
# 系统追踪111号进程
echo 111 > set_ftrace_pid
func_stack_trace
- 描述:是否记录堆栈跟踪
- 例子:
echo 1 > options/func_stack_trace # 启用栈回溯
funcgraph-proc
- 描述: 每行是否都会显示每个进程的命令。
- 例子:
echo 1 > ./options/funcgraph-proc # 每行都会显示每个进程的命令。
funcgraph-tail
- 描述: 结束花括号后是否增加函数尾部注释
- 例子:
echo 1 > ./options/funcgraph-tail # 结束花括号后增加函数尾部注释
ftrace使用
ftrace
可以做很多事情,我们最常用的功能有观察指定函数被执行, 观察指定函数调用关系,以及查看每个函数执行时耗时的时间。进而可以优化系统瓶颈。下面我分别用 function
和 function_graph
两种追踪器同时追踪do_sys_open
来看下效果
function跟踪器
# 进入 ftrace 的调试文件系统
cd /sys/kernel/debug/tracing
# 停止跟踪
echo 0 > tracing_on
# 清空trace下的输出
echo > trace
# 将do_sys_open加入脚本过滤列表
echo do_sys_open > set_ftrace_filter
# 启用function跟踪功能
echo function > current_tracer
# 启动跟踪
echo 1 > tracing_on
trace日志会自动保存在trace buffer里的在trace下进行输出
# 打开ls文件
ls
# 停止跟踪
echo 0 > tracing_on
# 查看跟踪结果
cat trace
来看下trace
跟踪结果
能看到两个信息:
- CPU1运行进程号为1947的
ls
进程执行__arm64_sys_openat
函数调用到do_sys_open
- 栈回溯信息
el0_sync
到do_sys_open
function_graph跟踪器
# 进入 ftrace 的调试文件系统
cd /sys/kernel/debug/tracing
# 停止跟踪
echo 0 > tracing_on
# 清空trace下的输出
echo > trace
# 将do_sys_open函数加入函数图功能
echo do_sys_open > set_graph_function
# 启用function_graph跟踪功能
echo function_graph > current_tracer
# 每行都会显示TASK/PID
echo funcgraph-proc > trace_options
# 结束花括号后增加函数尾部注释
echo 1 > ./options/funcgraph-tail
# 启动跟踪
echo 1 > tracing_on
# ls打开文件
ls
trace日志会自动保存在trace buffer里的在trace下进行输出
# 查看跟踪结果
cat trace
来看下trace
跟踪结果
能看到信息:
- 我们用
ls
命令打开文件的执行的函数流程do_sys_open
调到do_sys_openat2
,以此类推,每个函数调用所花费时间。具体的函数调用关系可以在内核里验证下是否准确
其他跟踪器大家感兴趣可以自行查阅资料进行自主学习
trace-cmd引入
从上面的例子看出使用 ftrace
还是挺麻烦的,我们需要手动的去控制多个文件,实际上使用 trace-cmd
更多一点。trace-cmd
是 ftrace 的前端工具,用于与 ftrace
进行交互。它提供了一个更方便的接口来配置和使用 ftrace
,避免了直接操作 debugfs
文件系统的麻烦。
安装trace-cmd
在使用 trace-cmd
之前,通常需要先安装它, 可以通过以下方式安装(以 Debian/Ubuntu 为例):
sudo apt-get install trace-cmd
trace-cmd常见命令
trace-cmd
的常见命令如下:
- 开启跟踪
trace-cmd start
这个命令会启动跟踪。使用默认的跟踪事件。
- 指定跟踪事件
trace-cmd start -e <event>
使用 -e
选项可以指定要跟踪的特定事件。例如:
trace-cmd start -e sched_switch
具体可以跟踪哪些事件可以用trace-cmd list
查看
- 显示可用的跟踪事件
trace-cmd list
列出所有可用的跟踪事件
- 查看当前跟踪状态
trace-cmd show
显示当前跟踪的状态,包括跟踪的事件和相关信息。效果和 cat /sys/kernel/debug/tracing/trace
一样
- 停止跟踪
trace-cmd stop
该命令停止当前的跟踪
- 记录跟踪数据,并导出到
trace.dat
文件中
trace-cmd record
记录跟踪数据并将其保存到文件中。默认情况下,数据将保存在 trace.dat
文件中
- 显示跟踪数据
trace-cmd report
此命令将显示在 trace.dat
文件中记录的跟踪数据,便于分析
- 清除跟踪数据
trace-cmd reset
清除当前的跟踪状态和数据, 效果和echo > /sys/kernel/debug/tracing/trace
一样
trace-cmd使用流程
使用流程如下所示
trace-cmd使用
接下来我们用 trace-cmd
来实现前面 ftrace
观测ls
进程打开文件调用到 do_sys_open
的函数调用图(function_graph
)效果。
首先我们记录下 do_sys_open
的调用流程到 trace.dat
,这步确定操作的目录是可读写目录否则无法生成 trace.dat
trace-cmd record -p function_graph -g do_sys_open -O funcgraph-proc ls
这时会在当前目录生成 trace.dat
文件。
接下来使用 report
读取 trace.dat
生成可读的文本数据进行输出
trace-cmd report trace.dat
看到的效果如下图所示
实际上是和操作ftrace
节点的命令查看效果差不多
总结
本文学习到了在Linux内核中ftrace
和trace-cmd
的使用,如果有疑问的话可以在评论区留言,对本篇文章学废的同学,可以一键三连!欢迎关注公众号[Linux随笔录],不定期分享Linux小知识