共计 2870 个字符,预计需要花费 8 分钟才能阅读完成。
uftrace
概述
uftrace 工具可用来跟踪和剖析用 C/C++ 编写的程序。它深受 Linux 内核的 ftrace 框架(尤其是函数图跟踪器)的启发,并反对用户空间程序。它反对各种命令和过滤器来帮忙分析程序的执行和性能。它的个性如下:
- 它能跟踪可执行文件中的每个函数并显示持续时间,它也能够跟踪内部库调用(入口和进口),通常也反对内部库嵌套的内部库或者外部函数调用。
- 它能够在性能级别显示具体的执行流程,并报告哪个函数的开销最高,它还显示了与执行环境相干的各种信息。
- 能够设置过滤器,以便在跟踪时排除或蕴含特定函数。此外,它还能够保留和显示函数参数和返回值。
- 它反对多过程和多线程应用程序。
- 如果内核有启用函数图跟踪器(CONFIG_FUNCTION_GRAPH_TRACER=y),那么它还能够跟踪内核函数(应用 -k 选项)。
实际
toolchain:gcc-9.1.0-2019.11-x86_64_arm-linux-gnueabihf
下 code
git clone https://github.com/namhyung/uftrace.git
编译
./configure --prefix=$PWD/output --host=arm-linux-gnueabihf
make -j5
make install
生成布局为:
运行
环境筹备
- 板子挂载共享目录
ifconfig eth0 up
ifconfig eth0 xxx.xxx.xxx.xxx
mount -t nfs xxx.xxx.xxx.xxx:/xxx /mnt -o nolock
- 将生成的 output/* 拷贝到共享目录的对应地位,板子上布局如下:
- 编译二进制程序要带上 -pg 或者 -finstrument-functions,本文全程以上面的程序为例子:
//multi_thread.c
#include <pthread.h>
#include <unistd.h>
void *thread_funcA(void *arg)
{printf("%s:%d\n", __FUNCTION__, __LINE__);
sleep(5);
printf("%s:%d\n", __FUNCTION__, __LINE__);
return NULL;
}
void *thread_funcB(void *arg)
{printf("%s:%d\n", __FUNCTION__, __LINE__);
sleep(10);
printf("%s:%d\n", __FUNCTION__, __LINE__);
return NULL;
}
int main(void)
{
pthread_t thidA;
pthread_t thidB;
printf("%s:%d\n", __FUNCTION__, __LINE__);
pthread_create(&thidA, NULL, thread_funcA, "funcA");
printf("%s:%d\n", __FUNCTION__, __LINE__);
pthread_create(&thidB, NULL, thread_funcB, "funcB");
printf("%s:%d\n", __FUNCTION__, __LINE__);
pthread_join(thidA, NULL);
printf("%s:%d\n", __FUNCTION__, __LINE__);
pthread_join(thidB, NULL);
printf("%s:%d\n", __FUNCTION__, __LINE__);
return 0;
}
编译如下:
arm-linux-gnueabihf-gcc -pg multi_thread.c -lpthread -o multi_thread
- 将生成的 multi_thread 放到共享目录里
- 须要留神的是,uftrace 会在当前目录创立 fifo/utrace.data,如果是在 windows 共享目录下,会提醒如下出错:
倡议切到板子上的 /tmp 目录: cd /tmp
- 最初再设置一下环境变量和动静库门路就能够欢快游玩了:
export PATH=/mnt/uftrace/bin:$PATH
export LD_LIBRARY_PATH=/mnt/uftrace/lib:$LD_LIBRARY_PATH
basic
目标程序执行完后,uftrace 就会输入每个函数的执行工夫。
uftrace /mnt/multi_thread
输入如下:
filters
- -F FUNC, –filter=FUNC
将过滤器设置为仅跟踪所选函数。
uftrace -F sleep -F printf /mnt/multi_thread
输入如下:
- -C FUNC, –caller-filter=FUNC
只显示所选函数的调用门路。
uftrace -C sleep -C printf /mnt/multi_thread
输入如下:
- -N FUNC, –notrace=FUNC
设置过滤器不跟踪所选函数
uftrace -N printf /mnt/multi_thread
输入如下:
- -t TIME, –time-filter=TIME
不显示设定工夫阈值以下的短小函数。
uftrace -t 1ms /mnt/multi_thread
Arguments Detection with Debug Info
应用 -a/–auto-args 去侦测带调试信息的二进制程序的函数参数和返回值。
uftrace -a /mnt/multi_thread
输入如下:
uftrace record
能够记录下 trace data,便于后续剖析。
uftrace record /mnt/multi_thread
生成如下:
uftrace replay
能够回放对应的 trace data,默认是回放当前目录的 uftrace.data。
uftrace replay
uftrace report
打印 trace data 的统计信息和摘要,默认是打印当前目录的 uftrace.data。
- basic
uftrace report
输入如下:
- -s
该选项可抉择按 total time/self time/calls 进行降序排序,默认按 total 降序排序。
- 按 total time 降序排序
uftrace report -s total
输入如下:
- 按 self time 降序排序
uftrace report -s self
- 按 calls 降序排序
uftrace report -s call
uftrace graph
显示函数调用图,默认是显示当前目录的 uftrace.data。
uftrace graph
输入如下:
总结
uftrace 还有很多弱小的个性,比方通过 dump 命令生成相应 trace data,可拿到 chrome 浏览器可视化展现或者生成火焰图;如果 configure 蕴含了 python,还能够编写 python 脚本定义函数入口和进口的钩子函数;如果编译加上 -mnop-mcount,还能够实现运行时动静跟踪;如果 configure 蕴含了 capstone,那能够实现齐全动静跟踪,而不必编译器反对。因而 uftrace 还是值得尝试一下。
参考
- github 主页
- 具体的官网 PPT
- 官网教程