从零开始之应用发开、linux应用(一、应用调试之strace)

  strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序。

     在Linux系统中,用户程序运行在一个沙箱(sandbox)里,用户进程不能直接访问计算机硬件设备。当进程需要访问硬件设备(如读取磁盘文件或接收网络数据等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可跟踪进程产生的系统调用,包括参数、返回值和执行所消耗的时间。若strace没有任何输出,并不代表此时进程发生阻塞;也可能程序进程正在自己的沙箱里执行某些不需要与系统其它部分发生通信的事情。strace从内核接收信息,且无需以任何特殊方式来构建内核。

当然它还可以做更多的事情:

strace可以过筛选出特定的系统调用。

strace可以记录系统调用的次数,时间,成功和失败的次数。

strace可以跟踪发给进程的信号。

strace可以通过pid附加到任何正在运行的进程上。

strace类似其他Unix系统上的truss,或者Sun's Dtrace

 

对于成熟的服务器或者桌面系统,strace是已经集成好的一个应用,对于从零开发的嵌入式系统,需要构建者自己来编译这个工具。

恰好我们就是自己构建的内核,所以应用程序都需要自己构建。

 

最新的是5.0,ok我们就使用这个最新的来构建这个工具。

从零开始之应用发开、linux应用(一、应用调试之strace)_第1张图片

这里给出源码地址,可以直接克隆下来源码构建。

https://github.com/strace/strace

 

克隆下来

从零开始之应用发开、linux应用(一、应用调试之strace)_第2张图片

 

构建配置,查看下面的configure里面的介绍,如果是工具的使用,就查看 README-linux-ptrace

 

 

从零开始之应用发开、linux应用(一、应用调试之strace)_第3张图片

 

从零开始之应用发开、linux应用(一、应用调试之strace)_第4张图片

 

生成自动配置文件 configure 

./bootstrap

 

我这边系统报错,说是找不到autoconf

 

那就先安装自动配置文件

sudo apt-get install automake

 

继续生成配置文件

./bootstrap

自动配置成功

从零开始之应用发开、linux应用(一、应用调试之strace)_第5张图片

 

配置

./configure --host=arm-none-linux-gnueabi CC=arm-none-linux-gnueabi-gcc

配置成功

从零开始之应用发开、linux应用(一、应用调试之strace)_第6张图片

 

编译

make

 

下面表示编译成功

从零开始之应用发开、linux应用(一、应用调试之strace)_第7张图片

生成的应用程序

 

拷贝我们自己的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;
}

 

关于这个工具的使用,我们可以直接使用帮助文档。

 

从零开始之应用发开、linux应用(一、应用调试之strace)_第8张图片

可以看到,这个工具的用法非常多,这里我们以最简单的一种用法为例来说一下它的使用。

 

-o + file,表示把这个程序的结果输出到file文件中。

 

可以看一下我们上面这个应用程序中,系统调用的一些输出结果。

从零开始之应用发开、linux应用(一、应用调试之strace)_第9张图片

刚打来文件,前面的都是一些头文件包含中的系统调用的结果。

一般我们不关系,我们只关心我们自己的应用程序的结果。

所以直接看输出信息的后面。

从零开始之应用发开、linux应用(一、应用调试之strace)_第10张图片

可以看到,我们这个app中系统调用的顺序,以及输出输出的参数。

比如open的返回值为3,表示文件描述符标号是3.

write返回值19,表示成功写入19个字符。

 

新创建的文件权限为063440,这个权限可以通过下表查看。

从零开始之应用发开、linux应用(一、应用调试之strace)_第11张图片

 

也可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# 

 

当然 本节只是简单的说一下这个工具的使用,后面章节项目应用程序部分,会直接使用这个工具来做调试。

 

 

 

你可能感兴趣的:(从零开始系列,从零开始学linux驱动)