【一文秒懂】Ftrace系统调试工具使用终极指南

news2024/9/22 13:39:39
img
我的圈子: 高级工程师聚集地
我是董哥,高级嵌入式软件开发工程师,从事嵌入式Linux驱动开发和系统开发,曾就职于世界500强公司!
创作理念:专注分享高质量嵌入式文章,让大家读有所得!
img

文章目录

    • 1、Ftrace是什么
    • 2、Ftrace的实现原理
      • 2.1 Ftrace框架图
      • 2.2 Ftrace是如何记录信息的
    • 3、如何使用Ftrace
      • 3.1 配置详解
      • 3.2 挂载debugfs文件系统
      • 3.3 traceing目录介绍
        • 3.3.1 trace
        • 3.3.2 trace_pipe
        • 3.3.3 tracing_on
        • 3.3.4 current_tracer
        • 3.3.5 available_filter_functions
        • 3.3.6 available_tracers
        • 3.3.7 buffer_size_kb
        • 3.3.8 buffer_total_size_kb
        • 3.3.9 set_ftrace_filter
        • 3.3.10 set_ftrace_notrace
        • 3.3.11 set_ftrace_pid
        • 3.3.12 set_graph_function
        • 3.3.12 set_graph_notrace
      • 3.4 简单使用示例
        • 3.4.1 函数追踪
        • 3.4.2 追踪图形显示
        • 3.4.3 动态过滤追踪
        • 3.4.4 重置追踪
    • 4、进阶用法
      • 4.1 追踪任意命令
      • 4.2 追踪指定函数的调用流程
      • 4.3 追踪指定模块的所有函数
    • 5、自动化管理
    • 6、总结

1、Ftrace是什么

FtraceFunction Trace的简写,由 Steven Rostedt 开发的,从 2008 年发布的内核 2.6.27 中开始就内置了。

Ftrace是一个系统内部提供的追踪工具,旨在帮助内核设计和开发人员去追踪系统内部的函数调用流程。

随着Ftrace的不断完善,除了追踪函数调用流程的作用外,还可以用来调试和分析系统的延迟和性能问题,并发展成为一个追踪类调试工具的框架。

除了Ftrace外,追踪类调试工具还包括:

Tracing overview

2、Ftrace的实现原理

为了帮助我们更好的使用Ftrace,我们有必要简单了解Ftrace的实现原理。

2.1 Ftrace框架图

Ftrace的框架图如下:

在这里插入图片描述

由框架图我们可以知道:

  • ftrace包括多种类型的tracers,每个tracer完成不同的功能
  • 将这些不同类型的tracers注册进入ftrace framework
  • 各类tracers收集不同的信息,并放入到Ring buffer缓冲区以供调用。

 

2.2 Ftrace是如何记录信息的

Ftrace采用了静态插桩和动态插桩两种方式来实现。

静态插桩

我们在Kernel中打开了CONFIG_FUNCTION_TRACER功能后,会增加一个-pg的一个编译选项,这个编译选项的作用就是为每个函数入口处,都会插入bl mcount跳转指令,使得每个函数运行时都会进入mcount函数。

Ftrace一旦使能,对kernel中所有的函数插桩,这带来的性能开销是惊人的,有可能导致人们弃用Ftrace功能。

为了解决这个问题,开发者推出了Dynamic ftrace,以此来优化整体的性能。

动态插桩

这里的动态,是指的动态修改函数指令。

  1. 编译时,记录所有被添加跳转指令的函数,这里表示所有支持追踪的函数。
  2. 内核将所有跳转指令替换为nop指令,以实现非调试状态性能零损失。
  3. 根据 function tracer 设置,动态将被调试函数的nop指令,替换为跳转指令,以实现追踪。

 

总而言之,Ftrace记录数据可以总结为以下几个步骤

  1. 打开编译选项-pg,为每个函数都增加跳转指令
  2. 记录这些可追踪的函数,并为了减少性能消耗,将跳转函数替换为nop指令
  3. 通过flag标志位来动态管理,将需要追踪的函数预留的nop指令替换回追踪指令,记录调试信息。

 

3、如何使用Ftrace

3.1 配置详解

CONFIG_FTRACE=y 							# 启用了 Ftrace
CONFIG_FUNCTION_TRACER=y					# 启用函数级别的追踪器
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y			# 表示内核支持图形显示
CONFIG_FUNCTION_GRAPH_TRACER=y				# 以图形的方式显示函数追踪过程
CONFIG_STACK_TRACER=y						# 启用堆栈追踪器,用于跟踪内核函数调用的堆栈信息。
CONFIG_DYNAMIC_FTRACE=y						# 启用动态 Ftrace,允许在运行时启用和禁用 Ftrace 功能。
CONFIG_HAVE_FTRACE_NMI_ENTER=y				# 表示内核支持非屏蔽中断(NMI)时进入 Ftrace 的功能
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y			# 表示内核支持通过 mcount 记录函数调用关系。
CONFIG_FTRACE_NMI_ENTER=y                   # 表示内核支持通过 mcount 记录函数调用关系。   
CONFIG_FTRACE_SYSCALLS=y					# 系统调用的追踪
CONFIG_FTRACE_MCOUNT_RECORD=y				# 启用 mcount 记录函数调用关系。
CONFIG_SCHED_TRACER=y						# 支持调度追踪
CONFIG_FUNCTION_PROFILER=y					# 启用函数分析器,主要用于记录函数的执行时间和调用次数
CONFIG_DEBUG_FS=y							# 启用 Debug 文件系统支持

上面只是介绍了部分配置,更多详细配置可自行了解。

并且上述配置不一定全部打开,勾选自己需要的即可,通常我们选择CONFIG_FUNCTION_TRACERCONFIG_HAVE_FUNCTION_GRAPH_TRACER即可,然后编译烧录到开发板。

 

3.2 挂载debugfs文件系统

Ftrace是基于debugfs调试文件系统的,所以我们的第一步就是先挂载debugfs

mount -t debugfs none /sys/kernel/debug

此时我们能够在/sys/kernel/debug下看到内核支持的所有的调试信息了。

# cd /sys/kernel/debug/
# ls
asoc                gpio                regmap
bdi                 ieee80211           sched_debug
block               memblock            sched_features
clk                 mmc0                sleep_time
device_component    mmc1                suspend_stats
devices_deferred    mtd                 tracing
dma_buf             opp                 ubi
extfrag             pinctrl             ubifs
fault_around_bytes  pm_qos              wakeup_sources

 

3.3 traceing目录介绍

/sys/kernel/debug目录下,包含的是kernel所有的调试信息,本章只关注与tracing目录,下面挑选一些比较重要的属性文件来分析。

 

万变不离其宗,如此复杂的框架,设计人员已经提供了README文件,里面详解了各个属性文件的含义,我建议抛弃本文,看README吧:)

3.3.1 trace

trace :包含当前追踪的内容,以人类可读的格式展现,通过echo > trace来清除。

 

3.3.2 trace_pipe

trace_pipetrace 一样,都是记录当前的追踪内容,但它和 trace 不一样的是:

  • trace_pipe 的读操作将会阻塞,直到有新的追踪数据进来为止;
  • 当前从trace_pipe 读取的内容将被消耗掉,再次读 trace_pipe 又会阻塞到新数据进来为止。

简单的来说,cat trace_pipe是堵塞读取,有数据就读,没数据就等待;而cat trace有没有数据都是直接返回的

 

3.3.3 tracing_on

tracing_on:向 tracing_on 写入 1,启用追踪;向 tracing_on 写入 0,停止追踪。

追踪使用 ring buffer 记录追踪数据。修改 tracing_on 不会影响 ring buffer 当前记录的内容。

 

3.3.4 current_tracer

current_tracer 表示当前启用的 tracer ,默认为 nop ,即不做任何追踪工作:

# cat current_tracer
nop

 

3.3.5 available_filter_functions

available_filter_functions:可以被追踪的函数列表,即可以写到 set_ftrace_filter,set_ftrace_notrace,set_graph_function,set_graph_notrace 文件的函数列表。

 

3.3.6 available_tracers

available_tracers 文件中包含的是当前编译到内核的 tracer 列表,也表示当前内核支持的tracer列表。

该列表的内容,就是可以写到 current_tracertracer 名。

# cat available_tracers
function_graph function nop
  • nop:表示为空,不追踪
  • function:追踪函数调用
  • function_graph:以图形形式追踪函数调用

 

3.3.7 buffer_size_kb

buffer_size_kb 记录 CPU buffer 的大小,单位为 KB

per_cpu/cpuX/buffer_size_kb 记录 每个CPU buffer 大小,单位为 KB 。可通过写 buffer_size_kb 来改变 CPU buffer 的大小。

 

3.3.8 buffer_total_size_kb

buffer_total_size_kb 记录所有 CPU buffer 的总大小,即所有 CPU buffer 大小总和。

如有 128 个 CPU buffer ,每个大小 7KB,则 buffer_total_size_kb 记录的总大小为 128 * 7KB = 896。

buffer_total_size_kb 文件是只读的。

 

3.3.9 set_ftrace_filter

set_ftrace_filter :过滤函数追踪,仅仅追踪写入该文件的函数名。

可填入的参数,可以通过available_filter_functions文件查看当前支持的函数名。

该过滤功能,也有很多其他变体,如追踪某个模块的函数调用等。

官方给的示例:

Format: :mod:<module-name>
example: echo :mod:ext3 > set_ftrace_filter		# 该模块必须是已经加载进去的模块

 

3.3.10 set_ftrace_notrace

set_ftrace_notrace:和 set_ftrace_filter 刚好相反,系统禁用对其中列举函数的追踪。

 

3.3.11 set_ftrace_pid

系统对 set_ftrace_pid 文件中指定的 PID进程进行追踪。

如果开启了 options/function-fork 选项,fork 的子进程的 PID 也会自动加入文件,同时该选项也会引起系统自动将退出进程的 PID 从文件中移除。

 

3.3.12 set_graph_function

此文件中列出的函数将导致函数图跟踪器仅跟踪这些函数以及它们调用的函数

但是该跟踪的记录,仍然受set_ftrace_filterset_ftrace_notrace 的影响。

 

3.3.12 set_graph_notrace

set_graph_function 类似,但当函数被命中时,将禁用函数图跟踪,直到退出函数。

 

更多干货可见:高级工程师聚集地,助力大家更上一层楼!

 

3.4 简单使用示例

一般我们挂载上debugfs后,tracing_on是处于打开状态的。

3.4.1 函数追踪

image-20240110110558815

 

3.4.2 追踪图形显示

image-20240110110617669

 

3.4.3 动态过滤追踪

image-20240110110641149

 

3.4.4 重置追踪
echo 0 > tracing_on			# 关闭trace
echo > trace				# 清空当前trace记录
cat available_tracers 		# 查看当前支持的追踪类型
echo function_graph > current_tracer 	# 设置当前的追踪类型
echo 1 > tracing_on			# 开启追踪
cat trace					# 查看追踪结果

 

4、进阶用法

上述章节,只是介绍了Ftrace最基本的命令,下面来看一下Ftrace在具体问题中的用法!

4.1 追踪任意命令

如何追踪我们执行的命令呢?

Ftrace支持追踪特定进程,通过set_ftrace_pid属性来设置指定进程。然后在该进程中,执行特定的命令。

首先我们需要设置好我们的追踪器

mount -t debugfs none /sys/kernel/debug
cd /sys/kernel/debug/tracing
echo 0 > tracing_on									# 关闭追踪器
echo function > current_tracer						# 设置当前追踪类别

在我们设置好追踪器后,使用如下命令,即可追踪我们执行的命令your_command

echo > trace; echo $$ > set_ftrace_pid; echo 1 > tracing_on; your_command; echo 0 > tracing_on

为什么要写成一条语句?

因为ftrace当打开时,在没有过滤的情况下,瞬间会抓取到内核所有的函数调用,为了更准确的抓取我们执行的命令,所以需要打开trace,执行完命令后,马上关闭。

 

4.2 追踪指定函数的调用流程

跟踪函数的时候,设置 echo 1 > options/func_stack_trace 即可在 trace 结果中获取追踪函数的调用栈。

mount -t debugfs none /sys/kernel/debug
cd /sys/kernel/debug/tracing
echo 0 > tracing_on									# 关闭追踪器
cat available_filter_functions | grep "xxxxxx"		# 搜索函数是否存在
echo xxxxxx > set_ftrace_filter						# 设定追踪的函数
echo function > current_tracer						# 设置当前追踪类别
echo 1 > options/func_stack_trace					# 记录堆栈信息
echo > trace										# 清空缓存
echo 1 > tracing_on									# 开始追踪

效果如下

# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 2/2   #P:3
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
     kworker/1:1-59    [001] ....   168.954199: mmc_rescan <-process_one_work
     kworker/1:1-59    [001] ....   168.954248: <stack trace>
 => mmc_rescan
 => process_one_work
 => worker_thread
 => kthread
 => ret_from_fork
 => 0

 

4.3 追踪指定模块的所有函数

要想我们的ko文件能够被Ftrace记录到,我们需要在编译模块的时候,加上编译参数-pg,这点很重要,否则你在available_filter_functions列表中,查找不到你想要的函数。

然后,需要我们设置过滤器,设置方法有以下几种:

  • 按模块直接过滤
# 示例
Format: :mod:<module-name>
example: echo :mod:ext3 > set_ftrace_filter

追踪ext3模块内的所有函数

 

  • 按函数直接过滤

如果该模块内的函数,命名都有一定的规则,可以按照正则表达式来过滤

# 示例
echo "mmc*" > set_ftrace_filter

过滤包含mmc字符的所有函数

 

  • 按照函数差异来过滤

如果函数命名没有规律,又想过滤该模块所有函数,该怎么办?

按照加载模块前后的函数差异,写入到文件中来过滤

cat available_filter_functions > /tmp/1.txt
cat available_filter_functions > /tmp/2.txt
diff /tmp/1.txt /tmp/2.txt > /tmp/3.txt
cat /tmp/3.txt | sed 's/^+//' | awk '{print $1}'	# 如果diff出来格式前带有+-号,需要手动去掉
cat /tmp/3.txt > set_ftrace_filter

 

5、自动化管理

Ftrace功能很强大,在内核层面我们通过echocat即可获取我们想要的所有信息,但是通过一次一次敲命令显得有些繁琐,自己也对常用的功能整合了一个自动化脚本,能够通过命令行,直接追踪特定模块、函数、命令,极大提高了调试效率。

PS:自动化脚本获取:公~号【嵌入式艺术】

# /root/common_trace.sh 
Usage: /root/common_trace.sh {module|funcs|funcs_stack|command|clear}
       /root/common_trace.sh module ext4 
       /root/common_trace.sh funcs sysfs 
       /root/common_trace.sh funcs_stack sysfs 
       /root/common_trace.sh command sysfs [functions] 
       /root/common_trace.sh clear

脚本主要实现的功能有:

  • 追踪指定模块,查看所有调用流程
  • 追踪指定函数,查看该函数的调用链
  • 追踪指定函数,获取堆栈信息
  • 追踪用户命令,查看所有调用流程,并可选择指定函数来查看调用流程。

脚本除了command功能外,其他功能都需要手动调用common_trace.sh clear来停止追踪。

 

6、总结

以上,介绍了Ftrace的由来,实现原理,以及如何使用Ftrace,并最终提供了自动化测试脚本,希望对大家有所帮助。

img
欢迎关注 公号&星球【嵌入式艺术】,董哥原创!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1404731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Armv8-M的TrustZone技术之内存属性单元

如果处理器包含Armv8-M安全扩展&#xff0c;则内存区域的安全状态由内部安全属性单元&#xff08;SAU&#xff0c;Secure Attribution Unit&#xff09;或外部实现定义的属性单元&#xff08;IDAU&#xff0c;Implementation Defined Attribution Unit&#xff09;的组合控制。…

【WinForm.NET开发】ToolStrip 控件体系结构

本文内容 ToolStripToolStripItem附件类 ToolStrip 和 ToolStripItem 类提供了一种灵活的可扩展系统&#xff0c;用于显示工具栏、状态和菜单项。 这些类都包含在 System.Windows.Forms 命名空间中 &#xff0c;它们的名称通常都带有“ToolStrip”前缀&#xff08;如 ToolStr…

yolov8 opencv dnn部署自己的模型

源码地址 本人使用的opencv c github代码,代码作者非本人 使用github源码结合自己导出的onnx模型推理自己的视频 推理条件 windows 10 Visual Studio 2019 Nvidia GeForce GTX 1070 opencv4.7.0 (opencv4.5.5在别的地方看到不支持yolov8的推理&#xff0c;所以只使用opencv…

HDMI、VGA、DVI、DB接口的区别

HDMI、VGA、DVI和DB&#xff08;也称为DisplayPort&#xff09;是不同类型的视频接口标准&#xff0c;它们用于连接计算机、显示器、电视和其他视频设备。 HDMI&#xff08;High-Definition Multimedia Interface&#xff0c;高清晰度多媒体接口&#xff09;&#xff1a;HDMI支…

C语言——静态通讯录的实现

今天我们来实现一下一个静态的通讯录&#xff1a; 我就先展示一下几个功能&#xff1a; 实现一个通讯录&#xff1b; 通讯录可以用来存储100个人的信息&#xff0c;每个人的信息包括&#xff1a;姓名、性别、年龄、电话、住址 提供方法&#xff1a; 添加联系人信息删除指定…

rancher和k8s接口地址,Kubernetes监控体系,cAdvisor和kube-state-metrics 与 metrics-server

为了能够提前发现kubernetes集群的问题以及方便快捷的查询容器的各类参数&#xff0c;比如&#xff0c;某个pod的内存使用异常高企 等等这样的异常状态&#xff08;虽然kubernetes有自动重启或者驱逐等等保护措施&#xff0c;但万一没有配置或者失效了呢&#xff09;&#xff0…

容器技术2-镜像与容器储存

目录 一、镜像制作 1、ddocker build 2、docker commit 二、镜像存储 1、公共仓库 2、私有仓库 三、镜像使用 四、容器存储 1、镜像元数据 2、存储驱动 3、数据卷 一、镜像制作 1、ddocker build 基于 Dockerfile 自动构建镜像 其机制为&#xff1a;每一行都会基于…

Go 的 Http 请求系统指南

文章目录 快速体验请求方法URL参数响应信息BodyStatusCodeHeaderEncoding 图片下载定制请求头复杂的POST请求表单提交提交文件 CookieClient 上设置 Cookie请求上设置 Cookie 重定向和请求历史超时设置总超时连接超时读取超时 请求代理错误处理总结 前几天在 “知乎想法” 谈到…

linux安装docker(入门一)

环境&#xff1a;centos 7(linux) 网站 官网: https://docs.docker.com/ Docker Hub 网站: https://hub.docker.com/ 容器官方概述 一句话概括容器&#xff1a;容器就是将软件打包成标准化单元&#xff0c;以用于开发、交付和部署。 容器镜像是轻量的、可执行的独立软件包 &…

Python小细节之代码极致简化到一行(5)(列表推导式)(技法慎用)

列表、推导式 引言简化前简化后讲解简化前简化后 应用结尾 引言 简单快速 大行其道 现在我又带着简化代码来了 我思考了下 简化的代码是技巧的体现 但是简短的代码里面 蕴藏着的是Python的精华 所以 我会更加详细的解析代码的内容 致力于让每个零基础的人都看懂 简化前 m…

DP活动:HMI-Board以太网数据监视器(一)以太网外设的使用

HMI-Board以太网数据监视器 开发工具  RT-Thread Studio/Keil MDK5&#xff08;固件开发、编译&#xff09;  SquareLine Studio&#xff08;LVGL UI设计工具&#xff09; 资料链接  RT-Thread Studio下载链接&#xff1a; https://download_redirect.rt-thread.org/…

C# 控制台进度条

最简单 namespace ProcessStu01 {internal class Program{static void Main(string[] args){for (int i 1; i < 100; i){Console.Write("\r{0,3}%",i);Thread.Sleep(50);}}} }第三方库 https://github.com/Mpdreamz/shellprogressbar using ShellProgressBar…

ubuntu source: not found

1、原因分析&#xff1a; shell 的解释器不是 bash&#xff0c;需把 shell 的解释器更改为 bash 2、ls -l /bin/sh 3、sudo dpkg-reconfigure dash 选择No 4、ls -l /bin/sh 5、reboot&#xff08;此步必须持续&#xff0c;否则无效&#xff09;

JUC并发编程-集合不安全情况以及Callable线程创建方式

6. 集合不安全 1&#xff09;List 不安全 //java.util.ConcurrentModificationException 并发修改异常&#xff01; public class ListTest {public static void main(String[] args) {List<Object> arrayList new ArrayList<>();for(int i1;i<30;i){new Thr…

020-信息打点-红蓝队自动化项目资产侦察企查产权武器库部署网络空间

020-信息打点-红蓝队自动化项目&资产侦察&企查产权&武器库部署&网络空间 #知识点&#xff1a; 1、工具项目-红蓝队&自动化部署 2、工具项目-自动化侦查收集提取 3、工具项目-综合&网络空间&信息 演示案例&#xff1a; ➢自动化-武器库部署-F8x ➢自…

uniapp中vue2项目导入高德地图

1、看官网新手入门链接导入原生高德地图&#xff1a; JS API 结合 Vue 使用-基础-进阶教程-地图 JS API 2.0|高德地图API (amap.com) 具体步骤&#xff1a; 第一步&#xff0c;安装插件 npm i amap/amap-jsapi-loader --save 第二步&#xff0c;在vue组件中写代码显示地图…

如何在科技创新中发挥国有企业的战略支撑作用?

要在科技创新中发挥国有企业的战略支撑作用&#xff0c;需要采取以下措施&#xff1a; 1. 强化国有企业创新主体地位&#xff1a;鼓励和支持国有企业加强技术创新、产品创新、组织创新和市场创新&#xff0c;提高自主创新能力。政府可以给予国有企业一定的政策和资金支持&…

MATLAB数据处理: 每种样本类型随机抽样

tn5;% 每种类型随机抽样数 indextrain[];% 训练样本序号集 for i1:typenumber index301 find(typemat i); n2length(index301); index302randperm(n2); index401index301(index302(1:tn)); indextrain[indextrain; index401]; end 该代码可以对大样…

【ZYNQ入门】第十篇、基于FPGA的图像白平衡算法实现

目录 第一部分、关于白平衡的知识 1、MATLAB 自动白平衡算法的实现 1.1、matlab代码 1.2、测试效果 1.3 测试源图 2、为什么摄像头采集的图像要做白平衡 3、自动白平衡算法总结 4、FPGA设计思路 4.1、实时白平衡的实现 4.2、计算流程优化思路 第二部分、硬件实…

使用PSIM软件生成DSP28335流水灯程序

最近在学习DSP28335芯片&#xff0c;然后在使用PSIM仿真软件时发现这个仿真软件也支持28335芯片&#xff0c;于是就想学习下如何在PSIM软件中使用DSP28335芯片。在PSIM自带的官方示例中有使用DSP28335芯片的相关例子。 工程下载链接 https://download.csdn.net/download/qq_20…