1、简介
ltrace的功能是能够跟踪进程的库函数调用,它会显现出哪个库函数被调用,而strace则是跟踪程序的每个系统调用。ltrace与strace使用的技术大体相同,但ltrace在对支持fork和clone方面,不如strace。strace在收到frok和clone等系统调用后,做了相应的处理,而ltrace没有。
2、安装
[root@RedHat_test ~]# yum install ltrace
3、ltrace命令常用格式
[root@RedHat_test ~]# man ltrace
-a : 对齐具体某个列的返回值。
-c : 计算时间和调用,并在程序退出时打印摘要。
-C : 解码低级别名称(内核级)为用户级名称。
-d : 打印调试信息。
-e : 改变跟踪的事件。
-f : 跟踪子进程。
-h : 打印帮助信息。
-i : 打印指令指针,当库调用时。
-l : 只打印某个库中的调用。
-L : 不打印库调用。
-n, --indent=NR : 对每个调用级别嵌套以NR个空格进行缩进输出。
-o, --output=file : 把输出定向到文件。
-p : PID 附着在值为PID的进程号上进行ltrace。
-r : 打印相对时间戳。
-s : STRLEN 设置打印的字符串最大长度。
-S : 显示系统调用。
-t, -tt, -ttt : 打印绝对时间戳。
-T : 输出每个调用过程的时间开销。
-u : USERNAME 使用某个用户id或组ID来运行命令。
-V, --version : 打印版本信息,然后退出。
4、程序实例
1.编写一个程序,打印Hello Word
[root@RedHat_test ~]# vim hello.c
#include <stdio.h>
int main() {
printf("Hello Word\n");
return 0;
}
2.用gcc
编译
[root@RedHat_test ~]# gcc hello.c -o hello
3.调用ltrace
[root@RedHat_test ~]# ltrace ./hello
__libc_start_main(0x40051d, 1, 0x7ffff6212798, 0x400540 <unfinished ...>
puts("Hello Word"Hello Word
) =11
+++exited (status 0) +++
-----------------------------------------------------------------------------------------
# 我们看到程序调用了puts();库函数做了输出
-----------------------------------------------------------------------------------------
5、打印系统调用
root@RedHat_test ~]# ltrace -S ./hello
brk@SYS(nil) =0x1a31000
mmap@SYS(nil, 4096, 3, 34, -1, 0) =0x7f08c3f98000
access@SYS("/etc/ld.so.preload", 04) =-2
open@SYS("/etc/ld.so.cache", 524288, 01) =3
fstat@SYS(3, 0x7ffc660983a0) =0
mmap@SYS(nil, 35957, 1, 2, 3, 0) =0x7f08c3f8f000
close@SYS(3) =0
open@SYS("/lib64/libc.so.6", 524288, 030376330520) =3
read@SYS(3, "\177ELF\002\001\001\003", 832) =832
fstat@SYS(3, 0x7ffc66098400) =0
mmap@SYS(nil, 3981792, 5, 2050, 3, 0) =0x7f08c39ab000
mprotect@SYS(0x7f08c3b6d000, 2097152, 0) =0
mmap@SYS(0x7f08c3d6d000, 24576, 3, 2066, 3, 1843200) =0x7f08c3d6d000
mmap@SYS(0x7f08c3d73000, 16864, 3, 50, -1, 0) =0x7f08c3d73000
close@SYS(3) =0
mmap@SYS(nil, 4096, 3, 34, -1, 0) =0x7f08c3f8e000
mmap@SYS(nil, 8192, 3, 34, -1, 0) =0x7f08c3f8c000
arch_prctl@SYS(4098, 0x7f08c3f8c740, 0x7f08c3f8d050, 34) =0
mprotect@SYS(0x7f08c3d6d000, 16384, 1) =0
mprotect@SYS(0x600000, 4096, 1) =0
mprotect@SYS(0x7f08c3f99000, 4096, 1) =0
munmap@SYS(0x7f08c3f8f000, 35957) =0
__libc_start_main(0x40051d, 1, 0x7ffc66099d58, 0x400540 <unfinished ...>
puts("Hello Word"<unfinished ...>
fstat@SYS(1, 0x7ffc66099b00) =0
mmap@SYS(nil, 4096, 3, 34, -1, 0) =0x7f08c3f97000
write@SYS(1, "Hello Word\n", 11Hello Word
) =11
<... puts resumed> ) =11
exit_group@SYS(0 <no return ...>
+++exited (status 0) +++
----------------------------------------------------------------------------------------
# 我们看到它实际是用SYS_write系统调用来做打印输出,其实write()函数是SYS_write的封装,SYS_write是真正的系统调用。
----------------------------------------------------------------------------------------
6、判断ltrace/strace的耗时
[root@RedHat_test ~]# ltrace -c dd if=/dev/urandom of=/dev/null count=1000
记录了1000+0的读入
记录了1000+0的写出
512000字节(512 kB)已复制,0.461573 秒,1.1 MB/秒
% time seconds usecs/call calls function
---------------------------------------------------------
53.36 0.473710 473710 1__libc_start_main
16.11 0.142987 142 1000read
15.57 0.138234 138 1000write
13.45 0.119368 119 1000memcpy
0.12 0.001034 258 4sigaction
0.11 0.001001 1001 1exit
0.10 0.000873 218 4__errno_location
0.09 0.000798 399 2dcgettext
0.09 0.000764 191 4close
0.08 0.000678 678 1setlocale
0.07 0.000654 218 3strchr
0.07 0.000590 196 3__fprintf_chk
0.06 0.000539 107 5strlen
0.06 0.000533 266 2open
0.06 0.000507 253 2dup2
0.05 0.000445 222 2malloc
0.05 0.000433 216 2sigismember
0.05 0.000417 208 2sigaddset
0.04 0.000335 167 2clock_gettime
0.03 0.000266 266 1getenv
0.03 0.000245 245 1lseek
0.03 0.000240 240 1bindtextdomain
0.03 0.000232 232 1sigemptyset
0.03 0.000231 231 1__cxa_atexit
0.03 0.000229 229 1textdomain
0.03 0.000228 114 2localeconv
0.03 0.000224 112 2__freading
0.03 0.000222 222 1getpagesize
0.02 0.000220 220 1strrchr
0.02 0.000219 219 1getopt_long
0.02 0.000216 216 1__strtoul_internal
0.02 0.000209 209 1__ctype_b_loc
0.01 0.000122 122 1dcngettext
0.01 0.000122 122 1fclose
0.01 0.000119 119 1__sprintf_chk
0.01 0.000116 116 1__fpending
0.01 0.000109 109 1fileno
0.01 0.000108 108 1memmove
0.01 0.000105 105 1exit_group
0.01 0.000094 94 1fflush
---------------------------------------------------------
100.00 0.887776 3063total
----------------------------------------------------------------------------------------
# 用-c选项,ltrace输出由进程创建的库调用,输出结果以调用过程的时间为准进行排序,因为是从urandom设备上读,这是一种产生随机数的设备,完成后,写入null设备。所以读过程花费了较多的时间。使用ltrace去捕获运行时函数,就好像在进程上系上一个调试工具,它占用了ltrace大量的时间,这里ltrace一共消耗了0.887776秒
----------------------------------------------------------------------------------------
[root@RedHat_test ~]# strace -c dd if=/dev/urandom of=/dev/null count=1000
记录了1000+0的读入
记录了1000+0的写出
512000字节(512 kB)已复制,0.0776944 秒,6.6 MB/秒
% time seconds usecs/call calls errors syscall
--------------------------------------------------------------
66.07 0.010263 10 1003 read
31.67 0.004920 5 1003 write
1.20 0.000186 19 10 2open
0.33 0.000052 5 11 close
0.23 0.000036 3 11 mmap
0.15 0.000024 4 6 fstat
0.13 0.000020 5 4 brk
0.08 0.000013 7 2 munmap
0.08 0.000013 7 2 dup2
0.04 0.000006 6 1 lseek
0.00 0.000000 0 4 mprotect
0.00 0.000000 0 4 rt_sigaction
0.00 0.000000 0 1 1access
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 arch_prctl
--------------------------------------------------------------
100.00 0.015533 2064 3total
----------------------------------------------------------------------------------------
# strace一共消耗了0.015533秒,strace把性能提升了80倍,这主要是strace在跟踪系统调用的时候不需要动态库,而ltrace是根据动态库来分析程序运行的。所以ltrace也只能跟踪动态库,不能跟踪静态库。事实上我们用ltrace和strace都可以发现程序在哪个系统调用时发生了性能瓶径。
----------------------------------------------------------------------------------------
7、ltrace/strace的相同点
ltrace与strace都可以指定PID,即对运行中的程序进行跟踪。
ltrace与strace都可以跟踪程序fork或clone子进程。
ltrace是用-f参数,而strace是用-f(fork/clone)和-F(vfork)。
如果文章有任何错误欢迎不吝赐教,其次大家有任何关于运维的疑难杂问,也欢迎和大家一起交流讨论。关于运维学习、分享、交流,笔者开通了微信公众号【运维猫】,感兴趣的朋友可以关注下,欢迎加入,建立属于我们自己的小圈子,一起学运维知识。群主还经营一家猫小铺饰品店,喜欢的小伙伴欢迎????前来下单。
扫描二维码
获取更多精彩
运维猫公众号
有需要技术交流的小伙伴可以加我微信,期待与大家共同成长,本人微信:
扫描二维码
添加私人微信
运维猫博主
扫码加微信
最近有一些星友咨询我知识星球的事,我也想继续在星球上发布更优质的内容供大家学习和探讨。运维猫公众号平台致力于为大家提供免费的学习资源,知识星球主要致力于即将入坑或者已经入坑的运维行业的小伙伴。
点击阅读原文 查看更多精彩内容!!!