小言_互联网的博客

使用trace查看函数调用关系|分析Linux性能

404人阅读  评论(0)

你好!这里是风筝的博客,

欢迎和我一起交流。


trace是内核自带的工具,相比于perf工具,trace只管抓trace数据并没有分析,perf在trace数据分析方面做出了很多成果。
但是我们现在就想看一下底层多调用关系,所以使用trace抓一下数据是非常有必要的,还可以分析一下驱动性能。

因为trace工具是内核自带的,所以我们配置一下内核就可以使用了:

Kernel hacking —>
         [*] Tracers —>
                 [*] Kernel Function Tracer
                 [*] Kernel Function Graph Tracer
                 [*] Trace syscalls
                 [*] enable/disable function tracing dynamically
                 [*] Kernel function profiler
                [*] Interrupts-off Latency Tracer

trace 通过 debugfs 向用户态提供了访问接口,所以还需要将 debugfs 编译进内核。激活对 debugfs 的支持,在 make menuconfig 时到 Kernel hacking 菜单下选中对 debugfs 文件系统的支持:
Kernel hacking —>
         -*- Debug Filesystem

系统启动后,进入文件系统,执行:

mount -t debugfs none /sys/kernel/debug/
cd /sys/kernel/debug/tracing/

挂载debugfs后即可使用trace。
tracing 目录下文件和目录比较多,有些是各种跟踪器共享使用的,有些是特定于某个跟踪器使用的。在操作这些数据文件时,使用 echo 命令来修改其值,也可以在程序中通过文件读写相关的函数来操作这些文件的值。

  • README文件提供了一个简短的使用说明,展示了 ftrace 的操作命令序列。可以通过 cat 命令查看该文件以了解概要的操作流程。
  • current_tracer用于设置或显示当前使用的跟踪器;使用 echo 将跟踪器名字写入该文件可以切换到不同的跟踪器。系统启动后,其缺省值为 nop ,即不做任何跟踪操作。在执行完一段跟踪任务后,可以通过向该文件写入 nop 来重置跟踪器。
  • available_tracers记录了当前编译进内核的跟踪器的列表,可以通过 cat 查看其内容;写 current_tracer 文件时用到的跟踪器名字必须在该文件列出的跟踪器名字列表中。
  • trace文件提供了查看获取到的跟踪信息的接口。可以通过 cat 等命令查看该文件以查看跟踪到的内核活动记录,也可以将其内容保存为记录文件以备后续查看。
  • set_graph_function设置要清晰显示调用关系的函数,显示的信息结构类似于 C 语言代码,这样在分析内核运作流程时会更加直观一些。在使用 function_graph 跟踪器时使用;缺省为对所有函数都生成调用关系序列,可以通过写该文件来指定需要特别关注的函数。
  • buffer_size_kb用于设置单个 CPU 所使用的跟踪缓存的大小。跟踪器会将跟踪到的信息写入缓存,每个 CPU 的跟踪缓存是一样大的。跟踪缓存实现为环形缓冲区的形式,如果跟踪到的信息太多,则旧的信息会被新的跟踪信息覆盖掉。注意,要更改该文件的值需要先将 current_tracer 设置为 nop 才可以。
  • tracing_on用于控制跟踪的暂停。有时候在观察到某些事件时想暂时关闭跟踪,可以将 0 写入该文件以停止跟踪,这样跟踪缓冲区中比较新的部分是与所关注的事件相关的;写入 1 可以继续跟踪。
  • available_filter_functions记录了当前可以跟踪的内核函数。对于不在该文件中列出的函数,无法跟踪其活动。
  • set_ftrace_filter和 set_ftrace_notrace在编译内核时配置了动态 ftrace (选中CONFIG_DYNAMIC_FTRACE 选项)后使用。前者用于显示指定要跟踪的函数,后者则作用相反,用于指定不跟踪的函数。如果一个函数名同时出现在这两个文件中,则这个函数的执行状况不会被跟踪。这些文件还支持简单形式的含有通配符的表达式,这样可以用一个表达式一次指定多个目标函数;注意,要写入这两个文件的函数名必须可以在文件 available_filter_functions 中看到。缺省为可以跟踪所有内核函数,文件 set_ftrace_notrace 的值则为空。
  • available_events 可以监控的事件

trace 当前包含多个跟踪器,用于跟踪不同类型的信息,比如进程调度、中断关闭等。可以查看文件 available_tracers 获取内核当前支持的跟踪器列表。在编译内核时,也可以看到内核支持的跟踪器对应的选项

  • nop跟踪器不会跟踪任何内核活动,将 nop 写入 current_tracer
    文件可以删除之前所使用的跟踪器,并清空之前收集到的跟踪信息,即刷新 trace 文件。
  • function跟踪器可以跟踪内核函数的执行情况;可以通过文件 set_ftrace_filter 显示指定要跟踪的函数。
    function_graph跟踪器可以显示类似 C 源码的函数调用关系图,这样查看起来比较直观一些;可以通过文件
  • set_grapch_function 显示指定要生成调用流程图的函数。 sched_switch跟踪器可以对内核中的进程调度活动进行跟踪。
  • irqsoff跟踪器和preemptoff跟踪器分别跟踪关闭中断的代码和禁止进程抢占的代码,并记录关闭的最大时长,preemptirqsoff跟踪器则可以看做它们的组合。

以上目录内容参考了:https://blog.csdn.net/trochiluses/article/details/9836329

那具体怎么用呢?

一、抓取函数调用流程关系

比如我们抓一次spi输出传输,驱动用的是kernel自带的spidev驱动:

echo 0 > tracing_on
echo function_graph > current_tracer
echo spidev_ioctrl > set_grapch_function 
echo 1 > tracing_on
./spidev_test
echo 0 > tracing_on
cat trace

spidev_ioctrl 被echo到set_grapch_function 属性里面,就可以查看整个spidev_ioctrl 函数的调用流程,但是实际上我们执行的时候会发现一个事情,抓取来的数据太多了,许多无关的、我们不太关心的函数调用关系也被抓进去了,导致抓出来的数据非常乱!
所以最好是利用set_ftrace_filter进行一些过滤。
所以针对这种情况,我们应该这样设置:

echo 0 > tracing_on
echo function_graph > current_tracer
echo *spi* > set_ftrace_filter
echo *dma* >> set_ftrace_filter
echo *spin* >> set_ftrace_notrace
echo 1 > tracing_on
./spidev_test
echo 0 > tracing_on
cat trace

在spi传输里,我们主要关系spi的函数和dma的函数,所以大概抓一下这些字眼即可,还可以按需自己添加过滤语句。
ps:因为spin_lock语句也带了spi字眼,也会被误抓进来,所以最后也把他剔除掉。
最后得出的数据就正常多了:

二、抓取函数耗时

有时候,也许我们也要通过程序的耗时来分析程序的性能,可以这么做:
同样也是以spidev驱动为例:

echo 0 > tracing_on
echo function_graph > current_tracer
echo spidev_ioctrl  > set_ftrace_filter
echo 1 > tracing_on
./spidev_test
echo 0 > tracing_on
cat trace

这样可以非常直观的看到spidev_ioctrl 执行的耗时。

未完,待续。。。。。。(放假了)

https://blog.csdn.net/pwl999/article/details/80514271
https://blog.csdn.net/pwl999/article/category/7733476


转载:https://blog.csdn.net/Guet_Kite/article/details/101791125
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场