跟踪 UNIX 应用程序的解决方案( 五 )


要想跟踪正在运行的程序,需要指定要跟踪的进程的进程 ID (PID) 。例如,在清单 6 中,跟踪的程序已经停止,但是没有报告错误 。这里使用 ps 工具列出正在运行的进程(见清单 7) 。
清单 7. 使用 ps 工具列出正在运行的进程
$ ps -ef|grep errlock 
 mc 15779 157470 18:26:59 pts/20:00 ./errlock 
 mc 157426800 18:26:36 pts/30:00 ./errlock 
 mc 15817 157840 18:28:44 pts/40:00 grep errlock 
 mc 157346800 18:25:00 pts/30:01 /usr/bin/eMacs-nox errlock.c 
$ truss -p 15779 
fcntl(3, F_SETLKW, 0x08047AC4) (sleeping...)
在输出中可以看到,已经调用了 fcntl() 函数,它要在一个文件上设置锁 。在这里,这个函数会一直等待到成功地设置锁,然后才继续运行 。不幸的是,另一个进程已经锁住了这个文件,所以第二个应用程序必须等待第一个应用程序使用完文件并释放锁 。
对于这种情况,truss 有点儿局限性:它无法指出要锁住哪个文件,也无法指出当前锁住了哪个文件,从而阻碍了第二个程序的执行 。这是因为跟踪过程是在已经调用了打开文件的函数之后启动的 。truss 和 strace 只跟踪在它们执行期间调用的函数;它们无法查明已经调用的函数 。
获取堆栈跟踪
可以看出,truss 对于监视整个程序很有用,但是对于监视已经启动的程序可能有点儿局限性 。如果使用基于 SVR4 的 Unix,比如 Solaris 或 AIX,那么 pstack 命令可能有帮助 。
pstack 命令实际上属于一组进程检查命令,这些命令输出正在运行的进程的相关信息 。其他工具包括 pfiles(输出进程使用的文件的列表)和 psig(显示信号和信号处理函数的列表) 。
在使用这些命令时,需要指定进程的 PID 。pstack 命令输出一个正在运行的进程的调用堆栈,显示在进程到达当前函数之前调用的函数 。例如,对正在等待被锁住的文件的进程使用 pstack,会产生清单 8 中的输出 。
清单 8. 对正在等待被锁住的文件的进程使用 pstack
$ pstack 15828 
15828: ./errlock 
 feef0877 fcntl(3, 7, 8047ac4) 
 feedcd49 fcntl(3, 7, 8047ac4, 8050e74)91 
 08050f10 main (1, 8047b24, 8047b2c)d8 
 08050cdc _start(1, 8047c08, 0, 8047c12, 8047c7d, 8047c8e)80
在这里,它没有提供我们需要的信息 。现在试试 pfiles(见清单 9) 。
清单 9. 使用 pfiles
$ pfiles 15856 
15856: ./errlock 
 Current rlimit: 256 file descriptors 
0: S_IFCHR mode:0620 dev:292,0 ino:989038936 uid:101 gid:7 rdev:24,3 
 O_RDWR|O_NOCTTY|O_LARGEFILE 
 /dev/pts/3 
1: S_IFCHR mode:0620 dev:292,0 ino:989038936 uid:101 gid:7 rdev:24,3 
 O_RDWR|O_NOCTTY|O_LARGEFILE 
 /dev/pts/3 
2: S_IFCHR mode:0620 dev:292,0 ino:989038936 uid:101 gid:7 rdev:24,3 
 O_RDWR|O_NOCTTY|O_LARGEFILE 
 /dev/pts/3 
3: S_IFREG mode:0666 dev:182,65545 ino:198 uid:101 gid:10 size:0 
 O_RDWR 
 advisory write lock set by process 15828 
 /export/home/mc/lockdemo
这些输出就比较有用了 。可以看到进程已经打开的文件称为 lockdemo ,因为 truss 显示正在等待文件锁,所以可能是这个文件导致了问题 。
truss 和 strace 都是被动的跟踪 。可以查看正在执行的函数,但是无法了解关于正在发生的情况的详细信息,也无法更有针对性地指定要跟踪的东西和跟踪时要输出的信息 。
用 DTrace 进行动态跟踪
【跟踪 UNIX 应用程序的解决方案】Solaris、FreeBSD 和 Mac OS X 内置的 Dynamic Tracing (DTrace) 功能提供一个更加动态的跟踪环境 。与 truss 和相似的工具不同,可以使用 DTrace 检查正在运行的程序的内部情况,而不只是查看系统调用 。另外,可以使用 DTrace 编写应用程序跟踪脚本,从而定制在跟踪过程中希望提取的信息 。

推荐阅读