使用strace,ltrace调试工具的乐趣

 

前言:
编写UNIX/LINUX系统程序让我冲满了乐趣。最近由于工作需要,我查看了df.c实现df命令的过程,偶然间了解了一个新的调试命令,就是关于strace。它可以让您真正的深入了解系统的功能,并且了解组合这些功能的各种各样的程序。它告诉了我关于UNIX/LINUX系统的底层的消息,带给我一个新的体验。使用strace工具,可以清楚的看清楚这些程序是如何调用,如何的使用参数。它的一切都暴露在你的面前。甚至你可以操作这些程序,以了解清楚他们是如何和操作系统之间进行最底层的对话。你将轻松的学习到一个软件是如何通过系统调用来实现他的功能的.而且作为一个程序设计师,你可以了解到在用户态和内核态是如何通过系统调用和信号来实现程序的功能的.


它的历史:
strace用来跟踪一个进程的系统调用或信号产生的情况,而 ltrace用来跟踪进程调用库函数的情况。而strace最初是为SunOS系统编写的,ltrace 最早出现在GNU/Debian Linux中。这两个工具现在也已被移植到了大部分Unix系统中,大多数Linux发行版都自带了strace和ltrace。

开始一个新的游戏:
首先我们从一个最简单的命令uptime开始,看看它到底在完成任务的过程中做了那些工作。输入命令
# eecho YANGLING

这个命令就是在我的终端上面我的大名 YANGLING
YANGLING

那么这么一个简单的命令究竟掩饰了它是如何实现的复杂过程呢?strace 命令可以带给我们一个新的体验。尝试一下
# strace echo 1
execve("/bin/echo", ["echo", "YANGLING"], [/* 25 vars */]) = 0
uname({sys="Linux", node="SERVER-AS4", ...}) = 0
brk(0)                                  = 0x87ce000
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=78864, ...}) = 0
old_mmap(NULL, 78864, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f6c000
close(3)                                = 0
open("/lib/tls/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\0\320\336\242\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1529136, ...}) = 0
old_mmap(0xa19000, 1227964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xa19000
old_mmap(0xb3f000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x125000) = 0xb3f000
old_mmap(0xb43000, 7356, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb43000
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f6b000
mprotect(0xb3f000, 8192, PROT_READ)     = 0
mprotect(0xa15000, 4096, PROT_READ)     = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7f6baa0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7f6c000, 78864)               = 0
brk(0)                                  = 0x87ce000
brk(0x87ef000)                          = 0x87ef000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=48500080, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7d6b000
mmap2(NULL, 1085440, PROT_READ, MAP_PRIVATE, 3, 0x1566) = 0xb7c62000
close(3)                                = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7c61000
write(1, "YANGLING\n", 9YANGLING
)               = 9
exit_group(0)                           = ?

显示了echo 命令究竟调用那些的系统调用的C函数以及调用的序列关系。特别注意一下:这些C函数是 最基本的系统调用对应的C函数,如果你对系统调用对应的C函数不清楚的话,可能你需要去阅读一下关于LINUX 内核代码对于这个部分的讲解。(那么fopen不是一个底层的系统调用open才是一个对应底层的系统调用。)

它还有那些功能:
在这里我就只列举一下它的常用功能
-f 参数表示 要跟踪fork或者vfork出来的子进程和所有的线程的流程
-o 输出到文件中
-p 指定的PID
-e 执行的系统调用被输出

 

我个人觉得用于跟踪内存泄露非常有用处

例如 strace -p nnn -e brk -f  (具体我记不清楚malloc函数中调用那个系统调用来分配内存了)

关于ltrace:
由于时间关系,在这里不再相信描述ltrace命令,至少它常用功能是跟踪库函数级的。这里要注意和strace跟踪的是系统调用级别的区别。我们可以根据实际情况来决定使用的那个命令

                                    阳凌 2009-09-18 V20090918-X1   yl.tienon@gmail.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值