linux下的调试工具ltrace与strace

ltrace能够跟踪进程的库函数调用,它会显现出哪个库函数被调用,而strace则是跟踪程序的每个系统调用.

下面是一个ltrace与strace的对比

1)系统调用的输出对比

我们用输出hello world的程序做如下测试:

#include <stdio.h>

int

main ()

{

printf("Hello world!\n");

return 0;

}

gcc hello.c -o hello

用ltrace跟踪hello程序,如下:

ltrace ./hello

__libc_start_main(0x8048354, 1, 0xbf869aa4, 0x8048390, 0x8048380 <unfinished ...>

puts("Hello world!"Hello world!

)                                                             = 13

+++ exited (status 0) +++

注:我们看到程序调用了puts();库函数做了输出.

用strace跟踪hello程序,如下:

strace ./hello

execve("./hello", ["./hello"], [/* 30 vars */]) = 0

brk(0)                                  = 0x83d4000

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f8a000

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat64(3, {st_mode=S_IFREG|0644, st_size=80846, ...}) = 0

mmap2(NULL, 80846, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f76000

close(3)                                = 0

open("/lib/libc.so.6", O_RDONLY)        = 3

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000?\270"..., 512) = 512

fstat64(3, {st_mode=S_IFREG|0755, st_size=1576952, ...}) = 0

mmap2(0xb6e000, 1295780, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6e000

mmap2(0xca5000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x137) = 0xca5000

mmap2(0xca8000, 9636, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xca8000

close(3)                                = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f75000

set_thread_area({entry_number:-1 -> 6, base_addr:0xb7f756c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0

mprotect(0xca5000, 8192, PROT_READ)     = 0

mprotect(0xb6a000, 4096, PROT_READ)     = 0

munmap(0xb7f76000, 80846)               = 0

fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f89000

write(1, "Hello world!\n", 13Hello world!

)          = 13

exit_group(0)                           = ?

Process 2874 detached

注:我们看到程序调用write()系统调用做了输出,同时strace还把hello程序运行时所做的系统调用都打印出来了.

同样的ltrace也可以把系统调用都打印出来,如下:

ltrace -S ./hello

SYS_execve(NULL, NULL, NULL)                                                     = 0xffffffda

SYS_brk(NULL)                                                                    = -38

SYS_mmap2(0, 4096, 3, 34, -1)                                                    = -38

SYS_access(0xb6798f, 4, 0xb6afc0, 0, 0xb6b6b4)                                   = -38

SYS_open("/etc/ld.so.cache", 0, 00)                                              = -38

SYS_fstat64(3, 0xbfba5414, 0xb6afc0, -1, 3)                                      = -38

SYS_mmap2(0, 80846, 1, 2, 3)                                                     = -38

SYS_close(3)                                                                     = -38

SYS_open("/lib/libc.so.6", 0, 027756452364???, 512)                              = -38

SYS_read(3, )                                                                    = -38

SYS_fstat64(3, 0xbfba5478, 0xb6afc0, 4, 1)                                       = -38

SYS_mmap2(0xb6e000, 0x13c5a4, 5, 2050, 3)                                        = -38

SYS_mmap2(0xca5000, 12288, 3, 2066, 3)                                           = -38

SYS_mmap2(0xca8000, 9636, 3, 50, -1)                                             = -38

SYS_close(3)                                                                     = -38

SYS_mmap2(0, 4096, 3, 34, -1)                                                    = -38

SYS_set_thread_area(0xbfba5960, 0xb7f5e6c0, 243, 0xb6afc0, 0)                    = -38

SYS_mprotect(0xca5000, 8192, 1, 7676, 0xca6e74)                                  = -38

SYS_mprotect(0xb6a000, 4096, 1, 896, 0)                                          = -38

SYS_munmap(0xb7f5f000, 80846 <unfinished ...>

__libc_start_main(0x8048354, 1, 0xbfba5dd4, 0x8048390, 0x8048380 <unfinished ...>

puts("Hello world!" <unfinished ...>

SYS_fstat64(1, 0xbfba5c20, 0xca6ff4, 0xca74c0, 0xca74c0)                         = 0

SYS_mmap2(0, 4096, 3, 34, -1)                                                    = 0xb7f72000

SYS_write(1, "Hello world!\n", 13Hello world!

)                                               = 13

<... puts resumed> )                                                             = 13

SYS_exit_group(0 <no return ...>

+++ exited (status 0) +++

注:我们看到它实际是用SYS_write系统调用来做打印输出,其实write()函数是SYS_write的封装,SYS_write是真正的系统调用.

二)ltrace/strace的耗时

ltrace -c dd if=/dev/urandom of=/dev/null count=1000

1000+0 records in

1000+0 records out

512000 bytes (512 kB) copied, 2.31346 seconds, 221 kB/s

% time     seconds  usecs/call     calls      function

------ ----------- ----------- --------- --------------------

84.88    4.942763        4942      1000 read

9.41    0.548195         548      1000 write

5.06    0.294716         294      1001 memcpy

0.11    0.006365        2121         3 __fprintf_chk

0.09    0.004969        4969         1 dcgettext

0.08    0.004850         808         6 strlen

0.05    0.002667        2667         1 setlocale

0.04    0.002579         644         4 sigaction

0.03    0.001869         467         4 close

0.03    0.001825         912         2 open64

0.03    0.001519         759         2 malloc

0.02    0.001187         593         2 __sprintf_chk

0.02    0.001176         588         2 clock_gettime

0.02    0.001169         389         3 __errno_location

0.02    0.001012         506         2 dcngettext

0.01    0.000814         814         1 lseek64

0.01    0.000757         757         1 getopt_long

0.01    0.000744         744         1 textdomain

0.01    0.000742         247         3 strchr

0.01    0.000634         634         1 __strtoull_internal

0.01    0.000602         602         1 getpagesize

0.01    0.000542         271         2 localeconv

0.01    0.000340         340         1 fclose

0.01    0.000300         300         1 memmove

0.00    0.000228         114         2 sigismember

0.00    0.000184         184         1 getenv

0.00    0.000170          85         2 sigaddset

0.00    0.000148          74         2 free

0.00    0.000093          93         1 bindtextdomain

0.00    0.000090          90         1 sigemptyset

0.00    0.000090          90         1 __cxa_atexit

0.00    0.000088          88         1 __ctype_b_loc

0.00    0.000074          74         1 __fpending

------ ----------- ----------- --------- --------------------

100.00    5.823501                  3057 total

注:

使用-c选项,ltrace输出由进程创建的库调用,输出结果以调用过程的时间为准进行排序,因为是从urandom设备上读,这是一种产生随机数的设备,完成后,写入null设备.

所以读过程花费了较多的时间.

使用ltrace去捕获运行时函数,就好像在进程上系上了一个调试工具,它占据了ltrace大量的时间,这里ltrace一共消耗了5.8秒

我们再来看一下strace所花费的时间,如下:

strace -c dd if=/dev/urandom of=/dev/null count=1000

1000+0 records in

1000+0 records out

512000 bytes (512 kB) copied, 0.894482 seconds, 572 kB/s

Process 3049 detached

% time     seconds  usecs/call     calls    errors syscall

------ ----------- ----------- --------- --------- ----------------

82.85    0.159393         159      1005           read

15.07    0.028995          29      1003           write

0.78    0.001494        1494         1           execve

0.42    0.000814         136         6           rt_sigaction

0.23    0.000446          41        11         1 close

0.23    0.000435          73         6           fstat64

0.21    0.000412          32        13           mmap2

0.21    0.000408          29        14         6 open

0.00    0.000000           0         1         1 access

0.00    0.000000           0         3           brk

0.00    0.000000           0         2           munmap

0.00    0.000000           0         1           uname

0.00    0.000000           0         4           mprotect

0.00    0.000000           0         1           _llseek

0.00    0.000000           0         1           rt_sigprocmask

0.00    0.000000           0         1           getrlimit

0.00    0.000000           0         1           set_thread_area

0.00    0.000000           0         1           set_tid_address

0.00    0.000000           0         2           clock_gettime

0.00    0.000000           0         1           set_robust_list

------ ----------- ----------- --------- --------- ----------------

100.00    0.192397                  2078         8 total

注:

strace一共消耗了0.19秒,strace把性能提升了30倍,这主要是strace在跟踪系统调用的时候不需要动态库,而ltrace是根据动态库来分析程序运行的.

所以ltrace也只能跟踪动态库,不能跟踪静态库.

事实上我们用ltrace和strace都可以发现程序在哪个系统调用时发生了性能瓶径.

ltrace用-T,而strace也用-T.

三)ltrace与strace的相同点

ltrace与strace都可以指定PID,即对运行中的程序进行跟踪.

ltrace -p PID与strace -p PID

ltrace与strace都可以跟踪程序fork或clone子进程.

ltrace是用-f参数,而strace是用-f(fork/clone)和-F(vfork).

时间: 2024-10-26 13:03:32

linux下的调试工具ltrace与strace的相关文章

Linux下gdb调试工具的使用

gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具. gdb主要完成四个方面的功能:(1).启动你的程序,可以按照你的自定义的要求随心所欲的运行程序:(2).可让被调试的程序在你所指定的调试的断点处停住(断点可以是条件表达式):(3).当程序被停住时,可以检查此时你的程序中所发生的事:(4).动态的改变你程序的执行环境. 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<;和>;)和shell通配符(*.?.[.])在

Linux下常用调试工具总结

kdump+crash使用: kdump是linux下分析内核崩溃原因的工具.系统崩溃时,kdump用于转储运行内存,捕获当前运行信息,将此时内存中所有运行状态和数据信息收集到一个dump core文件中(一般是在var/crash中的vmcore),以便后续分析.(ps:虚拟机中设置的crash memory为256M,过大或过小都不行) crash是用于分析kdump生成的core文件的工具.crash常用的指令: (1)log:显示内核消息缓存区 (2)bt:显示内核崩溃前的堆栈信息(可以

linux下can调试工具canutils安装过程记录

https://www.cnblogs.com/chenfulin5/p/6797756.html 一.下载源码 下载canutils和libsocketcan libsocketcan地址:https://public.pengutronix.de/software/libsocketcan/libsocketcan-0.0.11.tar.bz2 #0.0.11版本 canutils地址:https://public.pengutronix.de/software/socket-can/can

linux下串口调试工具/串口终端推荐: picocom

对于picocom, kermit, minicom, picocom 最简单易用,也完全符合我的使用需求. 安装(mint / ubuntu): $ sudo apt-get install picocom 使用: $ picocom -b 115200 /dev/ttyUSB0 (/dev/ttyUSB0 为串口设备文件,如果用的不是USB转串口,则为 /dev/ttyS*) (可以设置一个别名,如 alias pc='picocom -b 115200 /dev/ttyUSB0',这样在终

Linux下C语言编程基础学习记录

VIM的基本使用  LINUX下C语言编程 用gcc命令编译运行C语言文件 预处理阶段:将*.c文件转化为*.i预处理过的C程序. 编译阶段:将*.i文件编译为汇编代码*.s文件. 汇编阶段:将*.s文件转化为*.o的二进制目标代码文件. 链接阶段:将*.o文件转化为可执行文件. 生成可执行文件:将*.o转换为可执行文件. 执行可执行C语言文件. gcc常用选项列表 -c      只编译不链接,生成目标文件“.o” -S      只编译不汇编,生成编码代码 -E      只进行预编译,不做

Linux下C语言的编译全过程解读

Linux下C语言的编译全过程解读 我们总是在Linux下输入 gcc -o app main.c 即可编译好程序,对于具体的详细过程及流程,相信亲们就不太了解啦!下面给大家展示一下C编译器的解释全过程. Linux下编辑调试工具: gcc gdb  ,把高级语言编译成二进制可执行代码的工具. 把高级语言编译成二进制可执行文件的过程如下: 需要经历四个步骤: (1)预处理:去掉注释,进行宏替换(#define相关),头文件(#include)包含等工作. gcc–E test.c –o test

[转]五个Linux下用户空间的调试工具

有几个Linux下的用户空间调试工具和技术,它们用来分析用户空间的问题相当有用.它们是: 'print' 语句 查询 (/proc, /sys 等) 跟踪 (strace/ltrace) Valgrind (memwatch) GDB 让我们一个个地了解. 1.'print' 语句 这是一个基本的原始的调试问题的方法. 我们可以在程序中插入print语句来了解控制流和变量值. 虽然这是一个简单的技术, 但它有一些缺点. 程序需要进行编辑以添加'print'语句,然后必须重新编译,重新运行来获得输

Linux下调试程序方法

您可以用各种方法来监控运行着的用户空间程序:可以为其运行调试器并单步调试该程序,添加打印语句,或者添加工具来分析程序.本文描述了几种可以用来调试在 Linux 上运行的程序的方法.我们将回顾四种调试问题的情况,这些问题包括段错误,内存溢出和泄漏,还有挂起.本文讨论了四种调试 Linux 程序的情况.在第 1 种情况中,我们使用了两个有内存分配问题的样本程序,使用 MEMWATCH 和 Yet Another Malloc Debugger(YAMD)工具来调试它们.在第 2 种情况中,我们使用了

windows下的c语言和linux 下的c语言以及C标准库和系统API

1.引出我们的问题? 标准c库都是一样的!大家想必都在windows下做过文件编程,在linux下也是一样的函数名,参数都一样.当时就有了疑问,因为我们非常清楚 其本质是不可能一样的,源于这是俩个操作系统啊!但由于c标准库的封装就实现了接口一样.但是如果往深入,我们就非常清楚了在这层封装上还有一层封装其实就是操作系统对文件操作的封装,也就是文件IO.而我们c语言的封装叫标准IO,他们有什么区别那?显然标准iO是基于文件io的,标准IO调用了文件IO,也优化了文件IO,例如引入缓存机制. 2.上面