27unsigned long days_diff=0;
(gdb) bt
#0 calc_diff (day=26, month=3, year=2009) at ageindays.c:27
#1 0x00001e3d in main (argc=3, argv=0xbffff708) at ageindays.c:89
(gdb) p days_diff
$1 = 8041
(gdb)
通过 清单 2 中的输出可以看出,我们打开了调试器,通过指定名称在 calc_diff() 函数中设置了一个断点,然后在调试器中运行程序,提供与命令行相同的参数 。
当调试器到达创建的断点时,执行过程停止,您可以检查应用程序代码和调用的函数 。通过使用调试器,可以查看提供给函数的参数及其值(在这里是为目标日期提供的日期信息) 。执行停止之后,可以查看堆栈跟踪,查看代码中调用 calc_diff 函数的行,可以获得 days_diff 变量的值 。因为应用程序的执行过程已经暂停了,所以还可以修改变量的值 。这样就可以在应用程序中尝试使用不同的值,从而寻找潜在的问题 。
可以使用这些信息,因为定义了特定的调试信息(组成函数和变量名的符号)和其他元数据(比如定义函数的代码行) 。
必须在编译时把特定的调试信息添加到二进制应用程序中;更重要的是,必须访问源代码,才能把调试信息包含在编译的应用程序中 。如果无法识别函数名和变量,那么几乎不可能调试程序 。
跟踪与调试的对比
系统管理员(和开发人员)常常希望发现正在运行的程序中的错误 。例如,某个程序为什么造成了其他问题(比如内存和其他错误),应用程序的表现为什么不符合预期,它过去发生了什么情况 。在这种情况下,调试应用程序的特定方面往往没什么用 。需要查明的实际上是操作系统如何执行应用程序 。
在进行调试时,检查的是应用程序中定义的各个函数的执行过程 。调试主要关注应用程序本身,包括其中的函数和结构,通常会忽视应用程序向操作系统发出的系统调用和库函数调用 。调试能够提供关于应用程序的大量信息,但是对于了解操作系统如何执行应用程序帮助不大 。
在进行跟踪时,监视应用程序和操作系统之间的交互,常常会检查应用程序在执行期间调用的操作系统函数 。
除了这些差异之外,跟踪和调试之间的主要差异是,跟踪不要求访问源代码,也不要求以任何特殊方式编译应用程序 。这意味着可以跟踪操作系统附带的或第三方厂商提供的应用程序 。
通过跟踪应用程序,可以查明以下方面的情况:
内存使用量和映射内存的调用
在执行期间打开和关闭的文件
对不同文件的读和写操作
为给定的应用程序装载的库
下面先研究一下 truss 的输出,truss 是一种可以在 Solaris 和 AIX?上使用的工具 。
使用 truss 和 strace
在 Solaris 和 AIX 上可以使用 truss 工具,它能够跟踪应用程序中的系统调用和信号 。可以在 Linux?上使用的 strace 工具提供相似的功能 。在不同的系统上,还有提供相似信息的其他工具,包括 ktrace (FreeBSD) 和 trace 。
truss/strace 概述
truss 和 strace 工具提供相似的信息,但是命令行选项稍有差异 。使用这两种工具的标准方法都是把工具名放在要执行的命令前面 。
例如,清单 3 给出 truss 对于本教程前面提到的 ageindays 程序的输出 。
清单 3. truss 的输出
$ truss ./ageindays 24/1/1980 26/3/2009
execve("ageindays", 0x08047BBC, 0x08047BCC) argc = 3
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0)
= 0xFEFB0000
resolvepath("/usr/lib/ld.so.1", "/lib/ld.so.1", 1023) = 12
推荐阅读
- UNIX操作系统复杂的关机过程
- Unix文件名与Windows文件名的差异
- Unix中利用转义和引用来管理元字符
- 自动杀死Unix僵死的进程
- Unix操作系统中处理字符串问题的简单方式
- SCO unix三种安装BTLD的方式
- UNIX及SYBASE的安装
- 在Sco Unix下拨号上网
- 如何自动杀死UNIX僵死的进程
- 下 HP 服务器安装 SCOUNIX 5.0.4/5