Linux库函数调用工具—ltrace命令

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

如果文章有任何错误欢迎不吝赐教,其次大家有任何关于运维的疑难杂问,也欢迎和大家一起交流讨论。关于运维学习、分享、交流,笔者开通了微信公众号【运维猫】,感兴趣的朋友可以关注下,欢迎加入,建立属于我们自己的小圈子,一起学运维知识。群主还经营一家猫小铺饰品店,喜欢的小伙伴欢迎????前来下单。

扫描二维码

获取更多精彩

运维猫公众号

有需要技术交流的小伙伴可以加我微信,期待与大家共同成长,本人微信:

扫描二维码

添加私人微信

运维猫博主

扫码加微信

最近有一些星友咨询我知识星球的事,我也想继续在星球上发布更优质的内容供大家学习和探讨。运维猫公众号平台致力于为大家提供免费的学习资源,知识星球主要致力于即将入坑或者已经入坑的运维行业的小伙伴。

点击阅读原文  查看更多精彩内容!!!

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值