1.1.
1.1.1. strace介绍
strace是一个很有用的诊断、学习、调试工具。使用时无需重新编译程序,这也使得可以用来跟踪没有源代码的程序。系统调用和信号是发生在用户空间和内核空间边界处的事件,检查这些边界事件有助于隔离错误、检查完整性、跟踪错误。
使用starce工具来执行程序时,它会记录程序执行过程中调用的系统调用、接收到的信号。通过查看记录结果,可以知道程序打开了哪些文件(open)、打开是否成功、对文件进行了哪些读写操作(read/write/iotcl等)/映射了哪些内存(mmap)、向系统申请了多少内存等。
1.1.2. strace 移植
strace的源码为/work/debug/strace-4.5.15.tar.bz2,在arm平台上使用时要打上补丁strace-fix-arm-bad-syscall.patch
首先执行以下命令给strace打上补丁。
$tarxjf starce-4.5.15.tar.bz2
$catstarce-4.5.15
$patch–pl < strace-fix-arm-bad_syscall.patch
然后在strace-4.5.15目录下执行以下命令编译strace
$./configure–host=arm-linux CC=arm-linux-gcc
$make
在strace-4.5.15目录下生成一个名为strace的可执行程序,将它复制到开发板上根文件系统上即可使用。
1.1.3. 使用strace来调试程序
1.1.3.1. strace的用法
执行strace -help可以看到它的用法,如下所示:
下面是几个常用的选项
-f:除了跟踪当前进程外,还跟踪其子进程。
-o file:将输出信息写到文件中,而不是显示到标准错误输出。
-p pid:绑定到一个由pid对应的正在运行的进程,此参数常于调试后台进程。
-t :打印各系统调用被调用时的绝对时间,可以观察程序各部分的执行的时间。
-tt:与-t选项相似,打印时间精度为us。
-r:与-t选项相似,打印相对时间。
1.1.3.2. strace输出结果分析
通过strace,可以看到程序运行的细节。
运行strace cat /dev/null,可以看到它的输出结果如下,其中省略号表示还有其它系统调用没有列出来。
第一行表示shell进程通过系统调用execve来建立一个进程,即”cat /dev/null”对应的进程。
后面几行是open打开动态链接库,如果是静态程序连接的,这几个步骤将不需要。
然后“cat /dev/null”命令才是真正处理过程,首先打开“dev/null”文件,然后读取它的内容。
在strace的输出结果中,每一行对应一个系统调用:左起是系统调用的名字,紧接着是被包含在括号中的参数,最后是它的返回值。
系统调用出错时(返回值通常是-1),在返回值的后面会打印错误记号及其注释。
接收到信号时(如CTRL+C发送的SIGINT信号)也会将信号记号及其注释打印出来。
$strace–o sleep.log sleep 100 &
$kill–INT 868 // ps => sleep pid = 868
在sleep.log文件中可以发现如下字样,表示接收到SIGINT信号:
---SIGINT (Interrupt ) @ 0 (0) –
+++kill by SIGINT +++
1.1.3.3. 调试程序
在移植基于X的GUI程序时,就多次使用strace工具来跟踪程序,根据其中的出错信息建立了一些必需的目录,复制字库到特定的目录等。当不了解一个程序依赖于哪些目录和文件时,可以用strace工具来跟踪它。
下面举几个例子来说明如何使用strace来调试程序。
(1)使用strace来定位gtkboard的警告信息。
在移植hgtkboard时,它启动后在串口控制台上可以看到如下警告信息:
(gtkboard:855): Gdk-WARNING**: Error converting from UTF-8 to STRING:
Conversionfrom character set ‘UTF-8’ to ‘ISO-8859-1’ is not supported
解决办法为:把编译器lib目录下的gconv文件夹复制到开发板根文件系统的/usr/lib目录中。
是怎么知道这个解决方法的呢?如果深入分析gtkboard的代码,自然可以知道解决方法,但是效率太低,可以借助strace来分析。
通过以下命令启动gtkboard。
#strace –o gtkboard.loggtkboard &
然后查看gtkboard.log文件,发现如下字样:
open(“/usr/lib/gconv/gconv-modules.cache”,O_RDONLY)= -1 ENOENT(no such file or directory)
write(2,”\n(gtkboartd:855):Glib-WARNING**”…, 82) = 82
而交叉编译工具链中lib目录下刚好有gconv目录,把它复制到开发板根文件系统的/usr/lib目录后重新启动gtkboard,这些警告信息消失。
(2)使用strace来测量程序的执行时间。
如果发现某个程序突然执行很慢,通常需要找出其中哪部分代码执行的时间过长,使用strace工具可以轻易达到这个目的。
执行strace –r sleep 2命令,可以发现第2行和第3行的时间相差2s左右,符合”sleep 2”的意图。