DTrace是Solaris 10提供的一个非常强大的工具,在它的manual里有这么一句话:“use it, learn it, love it”,由此也可以看出它对UNIX程序员的吸引力。在这里提供一小段脚本,是前段时间我在研究FireEngine代码时写来练手的,可以用它来跟踪Solaris在TCP连接建立时的函数调用关系,稍作修改还可以用在很多其它场合。
DTrace的脚本语言叫D语言,它的语法和C语言很类似,但是如果把它和C语言混为一谈那就大错特错了。和其他脚本语言一样,要在文本的第一行加上执行的程序:
#! /usr/sbin/dtrace -s
这句话的意思表示运行结果采用缩进显示方式,语法很像C语言中的#pragma语句:
#pragma D option flowindent
BEGIN表示在进行DTrace probe之前需要执行的语句,如果对awk(1)比较熟悉的话,要理解它很容易。
BEGIN
{
PROTO_TCP = 6;
IP_HEADER = 20;
TH_SYN = 2;
}
这里初始化了几个常量,非别表示的是TCP在IP报文头中的协议号,IP报文头的长度,以及TCP SYN标志位的值。
再花一两句话时间介绍一下DTrace的程序结构。在一个DTrace的脚本中可以定义一个或多个probe description,它的结构如下:predicate,用谓词逻辑中的predicate(断言)来理解它挺合适,另外在C++的boost库中也有predicate,概念也很类似但是形式上很遥远。在一个probe description上,当断言的条件满足时,就会执行{}之间的语句。
probe descriptions
/ predicate /
{
action statements
}
显然,在下面这段probe中,表示在ip_rput函数的入口处开始跟踪,直到ip_rput函数结束。条件比较复杂,判断报文是不是设置了TCP SYN标记。
fbt::ip_rput:entry
/((ipha_t*)args[1]->b_rptr)->ipha_protocol == PROTO_TCP &&
(((tcph_t*)&args[1]->b_rptr[IP_HEADER])->th_flags[0] & TH_SYN) == TH_SYN/
{
self->traceme = 1;
printf("%s(%d, %x, %d)\n", probefunc, arg0, arg1, arg2);
}
fbt::ip_rput:return
/self->traceme/
{
self->traceme = 0;
exit(0);
}
fbt:::
/self->traceme/
{}
在机器上运行这个脚本,然后telnet过去,立刻就能看到运行结果,几乎是全部的函数调用关系。
值得指出的是,虽然DTrace很强大,但是由于DTrace只能跟踪函数的调用,对于更细节的跟踪...当然还得用mdb,在下一次有时间的时候我可能会写一点怎么用mdb来做跟踪的例子。
发表于 yu [Solaris] ( 六月 02, 2005 04:33 下午 ) Permalink | 评论 [0]

