strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序。
在Linux系统中,用户程序运行在一个沙箱(sandbox)里,用户进程不能直接访问计算机硬件设备。当进程需要访问硬件设备(如读取磁盘文件或接收网络数据等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可跟踪进程产生的系统调用,包括参数、返回值和执行所消耗的时间。若strace没有任何输出,并不代表此时进程发生阻塞;也可能程序进程正在自己的沙箱里执行某些不需要与系统其它部分发生通信的事情。strace从内核接收信息,且无需以任何特殊方式来构建内核。
当然它还可以做更多的事情:
strace可以过筛选出特定的系统调用。
strace可以记录系统调用的次数,时间,成功和失败的次数。
strace可以跟踪发给进程的信号。
strace可以通过pid附加到任何正在运行的进程上。
strace类似其他Unix系统上的truss,或者Sun's Dtrace
对于成熟的服务器或者桌面系统,strace是已经集成好的一个应用,对于从零开发的嵌入式系统,需要构建者自己来编译这个工具。
恰好我们就是自己构建的内核,所以应用程序都需要自己构建。
最新的是5.0,ok我们就使用这个最新的来构建这个工具。
这里给出源码地址,可以直接克隆下来源码构建。
https://github.com/strace/strace
克隆下来
构建配置,查看下面的configure里面的介绍,如果是工具的使用,就查看 README-linux-ptrace
生成自动配置文件 configure
./bootstrap
我这边系统报错,说是找不到autoconf
那就先安装自动配置文件
sudo apt-get install automake
继续生成配置文件
./bootstrap
自动配置成功
配置
./configure --host=arm-none-linux-gnueabi CC=arm-none-linux-gnueabi-gcc
配置成功
编译
make
下面表示编译成功
生成的应用程序
拷贝我们自己的arm开发板所在的文件系统上
下面我们以一个简单的例子为例来使用一下这个工具
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
int fd = 0;
char buf[] = "You're a good man!\n";
int len = 0;
/*
* 创建一个文件
*/
fd = open("file.txt", O_CREAT|O_RDWR);
if(fd < 0) {
perror("open fail\n");
exit(1);
}
/*
* 写入一段字符串
*/
len = strlen(buf);
if(write(fd, buf, len) < len) {
perror("write fail\n");
exit(1);
}
/*
* 关闭文件
*/
close(fd);
return 0;
}
关于这个工具的使用,我们可以直接使用帮助文档。
可以看到,这个工具的用法非常多,这里我们以最简单的一种用法为例来说一下它的使用。
-o + file,表示把这个程序的结果输出到file文件中。
可以看一下我们上面这个应用程序中,系统调用的一些输出结果。
刚打来文件,前面的都是一些头文件包含中的系统调用的结果。
一般我们不关系,我们只关心我们自己的应用程序的结果。
所以直接看输出信息的后面。
可以看到,我们这个app中系统调用的顺序,以及输出输出的参数。
比如open的返回值为3,表示文件描述符标号是3.
write返回值19,表示成功写入19个字符。
新创建的文件权限为063440,这个权限可以通过下表查看。
也可c参数,来查看各个系统调用在整个应用中的占用时间百分比,已经具体时间。
strace -c -o log.txt ./create_file
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.00 0.002064 108 19 16 open
18.47 0.000733 48 15 15 stat64
10.86 0.000431 61 7 mmap2
4.54 0.000180 60 3 close
4.54 0.000180 45 4 mprotect
2.27 0.000090 90 1 write
2.19 0.000087 43 2 fstat64
2.12 0.000084 42 2 read
1.69 0.000067 67 1 1 access
0.53 0.000021 21 1 uname
0.40 0.000016 16 1 brk
0.40 0.000016 16 1 set_tls
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.003969 58 32 total
一般通过strace + -c参数,可以判断程序的具体性能,以便确定是否需要优化,以及优化的目标。
也可以查看某个shell命令的调用方式,比如
strace cat log.txt
execve("/bin/cat", ["cat", "log.txt"], 0x7ede9e74 /* 10 vars */) = 0
uname({sysname="Linux", nodename="linux", ...}) = 0
brk(NULL) = 0x206000
brk(0x206d20) = 0x206d20
set_tls(0x2064c0) = 0
brk(0x227d20) = 0x227d20
brk(0x228000) = 0x228000
getuid32() = 0
open("log.txt", O_RDONLY|O_LARGEFILE) = 3
sendfile64(1, 3, NULL, 16777216% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.00 0.002064 108 19 16 open
18.47 0.000733 48 15 15 stat64
10.86 0.000431 61 7 mmap2
4.54 0.000180 60 3 close
4.54 0.000180 45 4 mprotect
2.27 0.000090 90 1 write
2.19 0.000087 43 2 fstat64
2.12 0.000084 42 2 read
1.69 0.000067 67 1 1 access
0.53 0.000021 21 1 uname
0.40 0.000016 16 1 brk
0.40 0.000016 16 1 set_tls
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.003969 58 32 total
) = 999
sendfile64(1, 3, NULL, 16777216) = 0
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
[root@linux]/app#
当然 本节只是简单的说一下这个工具的使用,后面章节项目应用程序部分,会直接使用这个工具来做调试。