点击上方“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的使用

Linux内核调试 | 分析Oops错误

Linux内核调试 | 动态输出的使用

Linux内核调试 | printk的原理及使用

那如果要判断内核函数是否执行和调用关系我们知道要用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优势 

  1. 灵活性ftrace 可以跟踪内核中的几乎所有函数调用,并允许用户选择他们希望跟踪的特定函数。
  2. 低开销:与其他跟踪工具相比,ftrace 的开销较小,因此适合在生产环境中使用。
  3. 多种跟踪方式
  • 函数跟踪:跟踪函数的进入和退出。
  • 事件跟踪:可以跟踪特定的内核事件(如调度、I/O 操作等)。
  • 性能分析:收集执行时间、调用频率等信息,帮助分析性能问题。
  1. 可视化工具:通过 trace-cmd 和 perf 等工具,用户可以将 ftrace 收集的数据可视化,以帮助分析。
  2. 动态跟踪:支持动态启用和禁用跟踪,而无需重新编译内核。

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目录下的节点如下图所示

Linux内核调试追踪 | ftrace的使用(一)_数据

看起来挺多的,下面我只讲常用的节点信息,大家想了解更多可以看下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跟踪结果

Linux内核调试追踪 | ftrace的使用(一)_ci_02

能看到两个信息:

  1. CPU1运行进程号为1947的 ls 进程执行__arm64_sys_openat 函数调用到 do_sys_open
  2. 栈回溯信息 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跟踪结果

Linux内核调试追踪 | ftrace的使用(一)_数据_03

能看到信息:

  • 我们用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 的常见命令如下:

  1. 开启跟踪
trace-cmd start

这个命令会启动跟踪。使用默认的跟踪事件。

  1. 指定跟踪事件
trace-cmd start -e <event>

使用 -e 选项可以指定要跟踪的特定事件。例如:

trace-cmd start -e sched_switch

具体可以跟踪哪些事件可以用trace-cmd list查看

  1. 显示可用的跟踪事件
trace-cmd list

列出所有可用的跟踪事件

  1. 查看当前跟踪状态
trace-cmd show

显示当前跟踪的状态,包括跟踪的事件和相关信息。效果和 cat /sys/kernel/debug/tracing/trace一样

  1. 停止跟踪
trace-cmd stop

该命令停止当前的跟踪

  1. 记录跟踪数据,并导出到trace.dat文件中
trace-cmd record

记录跟踪数据并将其保存到文件中。默认情况下,数据将保存在 trace.dat 文件中

  1. 显示跟踪数据
trace-cmd report

此命令将显示在 trace.dat 文件中记录的跟踪数据,便于分析

  1. 清除跟踪数据
trace-cmd reset

清除当前的跟踪状态和数据, 效果和echo > /sys/kernel/debug/tracing/trace一样

trace-cmd使用流程 

使用流程如下所示

Linux内核调试追踪 | ftrace的使用(一)_数据_04

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 文件。

Linux内核调试追踪 | ftrace的使用(一)_ci_05

接下来使用 report 读取 trace.dat 生成可读的文本数据进行输出

trace-cmd report trace.dat

看到的效果如下图所示

Linux内核调试追踪 | ftrace的使用(一)_函数调用_06

实际上是和操作ftrace节点的命令查看效果差不多

总结 

本文学习到了在Linux内核中ftracetrace-cmd的使用,如果有疑问的话可以在评论区留言,对本篇文章学废的同学,可以一键三连!欢迎关注公众号[Linux随笔录],不定期分享Linux小知识