Ftrace设计作为一个内部的tracer提供给系统的开发者和设计者,帮助他们弄清kernel正在发生的行为,它能够调式分析延迟和性能问题。对于前一章节,我们学习了Ftrace发展到现在已经不仅仅是作为一个function tracer了,它实际上成为了一个通用的trace工具的框架
通过前面两节的学习,我们知道了什么是ftrace,能够解决什么问题,从这章开始我们主要是学习,怎么去使用ftreace解决问题。
1 ftrace基础用法
ftrace 通过 debugfs 向用户态提供访问接口。配置内核时激活 debugfs 后会创建目录 /sys/kernel/debug ,debugfs 文件系统就是挂载到该目录。要挂载该目录,需要将如下内容添加到 /etc/fstab 文件:
debugfs /sys/kernel/debug debugfs defaults 0 0
或者可以在运行时挂载:
mount -t debugfs debugfs /sys/kernel/debug
其中重点关注以下文件
trace查看选择器
查看支持的跟踪器available_tracers
root@100ask:/sys/kernel/debug/tracing# cat available_tracers
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop
查看当前的跟踪器current_tracer ,可以echo选择
root@100ask:/sys/kernel/debug/tracing# cat current_tracer
nop
trace使能
tracing_on :是否往循环buffer写跟踪记录,可以echo设置
root@100ask:/sys/kernel/debug/tracing# cat tracing_on
trace过滤器选择(可选)
1.2 function trace实例
function,函数调用追踪器, 跟踪函数调用,默认跟踪所有函数,如果设置set_ftrace_filter, 则跟踪过滤的函数,可以看出哪个函数何时调用。
available_filter_functions:列出当前可以跟踪的内核函数,不在该文件中列出的函数,无法跟踪其活动
enabled_functions:显示有回调附着的函数名称。
function_profile_enabled:打开此选项,在trace_stat中就会显示function的统计信息。
set_ftrace_filter:用于指定跟踪的函数
set_ftrace_notrace:用于指定不跟踪的函数
set_ftrace_pid:用于指定要跟踪特定进程的函数
Disable tracer:
echo 0 > tracing_on
设置 tracer 类型为 function:
echo function > current_tracer
set_ftrace_filter 表示要跟踪的函数,这里我们只跟踪 dev_attr_show 函数:
echo dev_attr_show > set_ftrace_filter
Enable tracer:
echo 1 > tracing_on
提取trace结果:
function 跟踪器可以跟踪内核函数的调用情况,可用于调试或者分析 bug ,还可用于了解和观察 Linux 内核的执行过程。同时ftrace允许你对一个特定的进程进行跟踪,在/sys/kernel/debug/tracing目录下,文件set_ftrace_pid的值要更新为你想跟踪的进程的PID。
echo $PID > set_ftrace_pid
1.3 function_graph Trace 实例
function_graph 跟踪器则可以提供类似 C 代码的函数调用关系信息。通过写文件 set_graph_function 可以显示指定要生成调用关系的函数,缺省会对所有可跟踪的内核函数生成函数调用关系图。
函数图跟踪器对函数的进入与退出进行跟踪,这对于跟踪它的执行时间很有用。函数执行时间超过10微秒的标记一个“+”号,超过1000微秒的标记为一个“!”号。通过echo function_graph > current_tracer可以启用函数图跟踪器。
与 function tracer 类似,设置 function_graph 的方式如下:
设置 tracer 类型为 function_graph:
echo function_graph > current_tracer
set_graph_function 表示要跟踪的函数:
echo __do_fault > set_graph_function
echo 1 > tracing_on
捕捉到的 trace 内容:
我们跟踪的是 __do_fault
函数,但是 function_graph tracer 会跟踪函数内的调用关系和函数执行时间,可以协助我们确定代码执行流程。比如一个函数内部执行了很多函数指针,不能确定到底执行的是什么函数,可以用 function_graph tracer 跟踪一下。
CPU 字段给出了执行函数的 CPU 号,本例中都为 1 号 CPU。
DURATION 字段给出了函数执行的时间长度,以 us 为单位。
FUNCTION CALLS 则给出了调用的函数,并显示了调用流程。
需要注意:
对于不调用其它函数的函数,其对应行以“;”结尾,而且对应的 DURATION 字段给出其运行时长;
对于调用其它函数的函数,则在其“}”对应行给出了运行时长,该时间是一个累加值,包括了其内部调用的函数的执行时长。DURATION 字段给出的时长并不是精确的,它还包含了执行 ftrace 自身的代码所耗费的时间,所以示例中将内部函数时长累加得到的结果会与对应的外围调用函数的执行时长并不一致;不过通过该字段还是可以大致了解函数在时间上的运行开销的。
1.4 wakeup
wakeup tracer追踪普通进程从被唤醒到真正得到执行之间的延迟。
1.5 wakeup-rt
non-RT进程通常看平均延迟。RT进程的最大延迟非常有意义,反应了调度器的性能
2 trace event 用法
2.1 trace event 简介
trace event 就是利用 ftrace 框架,实现低性能损耗,对执行流无影响的一种信息输出机制。相比 printk,trace event:
不开启没有性能损耗
开启后不影响代码流程
不需要重新编译内核即可获取 debug 信息
2.2 使用实例
上面提到了 function
的 trace,在 ftrace 里面,另外用的多的就是 event
的 trace,我们可以在 events
目录下面看支持那些事件:
上面列出来的都是分组的,我们可以继续深入下去,譬如下面是查看 sched
相关的事件
对于某一个具体的事件,我们也可以查看:
上述目录里面,都有一个 enable
的文件,我们只需要往里面写入 1,就可以开始 trace 这个事件。譬如下面就开始 trace sched_wakeup
这个事件
我们也可以 trace sched
里面的所有事件
当然也可以 trace 所有的事件:
3 高级技巧
查看函数调用栈
查看函数调用栈是内核调试最最基本得需求,常用方法:
trace 函数的时候,设置 echo 1 > options/func_stack_trace
即可在 trace 结果中获取追踪函数的调用栈。
以 dev_attr_show
函数为例,看看 ftrace 如何帮我们获取调用栈:
#cd /sys/kernel/debug/tracing
#echo 0 > tracing_on
#echo function > current_tracer
#echo schedule > set_ftrace_filter
// 设置 func_stack_trace
#echo 1 > options/func_stack_trace
#echo 1 > tracing_on
如何跟踪一个命令,但是这个命令执行时间很短
我们可以设置ftrace过滤器控制相关文件
文件名 | 功能 |
---|
set_ftrace_filter | function tracer 只跟踪某个函数 |
set_ftrace_notrace | function tracer 不跟踪某个函数 |
set_graph_function | function_graph tracer 只跟踪某个函数 |
set_graph_notrace | function_graph tracer 不跟踪某个函数 |
set_event_pid | trace event 只跟踪某个进程 |
set_ftrace_pid | function/function_graph tracer 只跟踪某个进程 |
如果这时候问:如何跟踪某个进程内核态的某个函数?
答案是肯定的,将被跟踪进程的 pid 设置到 set_event_pid/set_ftrace_pid
文件即可。
但是如果问题变成了,我要调试 kill
的内核执行流程,如何办呢?
因为 kill
运行时间很短,我们不能知道它的 pid,所以就没法过滤了。
调试这种问题的小技巧,即 脚本化,这个技巧在很多地方用到:
sh -c "echo $$ > set_ftrace_pid; echo 1 > tracing_on; kill xxx; echo 0 > tracing_on"
如何跟踪过滤多个进程?多个函数?
函数名雷同,可以使用正则匹配
# cd /sys/kernel/debug/tracing
# echo 'dev_attr_*' > set_ftrace_filter
# cat set_ftrace_filter
dev_attr_store
dev_attr_show
4 前端工具
我们可以手工操作/sys/kernel/debug/tracing路径下的大量的配置文件接口,来使用ftrace的强大功能。但是这些接口对普通用户来说太多太复杂了,我们可以使用对ftrace功能进行二次封装的一些命令来操作。
trace-cmd就是ftrace封装命令其中的一种。该软件包由两部分组成
4.1 trace-cmd
下载编译ARM64 trace-cmd方法
git clone [https://github.com/rostedt/trace-cmd.git](https://github.com/rostedt/trace-cmd.git)
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make
先通过 record 子命令将结果记录到 trace.dat,再通过 report 命令进行结果提取。命令解释:
在很有情况下不能使用函数追踪,需要依赖 事件追踪 的支持,例如:
4.2 kernelshark图形化分析数据
trace-cmd report
主要是使用统计的方式来找出热点。如果要看vfs_read()
一个具体的调用过程,除了使用上一节的trace-cmd report
命令,还可以使用kernelshark图形化的形式来查看,可以在板子上使用trace-cmd record
记录事件,把得到的trace.data放到linux 桌面系统,用kernelshark
打开,看到图形化的信息
来源:https://blog.csdn.net/u012489236/article/details/119519361
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
推荐阅读
【1】jetson nano开发使用的基础详细分享
【2】Linux开发coredump文件分析实战分享
【3】CPU中的程序是怎么运行起来的 必读
【4】cartographer环境建立以及建图测试
【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比
本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。