linux动态调试工具,Linux的调试工具ltrace与strace方法总结

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

下面是一个ltrace与strace的对比

一、系统调用的输出对比

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

#include

int

main ()

{

printf("Hello world!\n");

return 0;

}

gcc hello.c -o hello

2.用ltrace跟踪hello程序,如下:

ltrace ./hello

__libc_start_main(0x8048354, 1, 0xbf869aa4, 0x8048390, 0x8048380

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

__libc_start_main(0x8048354, 1, 0xbfba5dd4, 0x8048390, 0x8048380

puts("Hello world!"

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

+++ 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_addres

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).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值