全部分类 | General | Music | Solaris

« 正式开始blog | Main | Hello World in KMDB... »
 20050602 星期四 2005年06月02日

用DTrace跟踪TCP报文

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]
反向跟踪 URL: http://blogs.sun.com/yu/entry/%C3%83%C2%A7%C3%82%C2%94%C3%82%C2%A8dtrace%C3%83%C2%A8%C3%82%C2%B7%C3%82%C2%9F%C3%83%C2%A8%C3%82%C2%B8%C3%82%C2%AAtcp%C3%83%C2%A6%C3%82%C2%8A%C3%82%C2%A5%C3%83%C2%A6%C3%82%C2%96%C3%82%C2%87
评论:

发表一条评论:

姓名:
电子邮件地址:
URL:

您的评论:

HTML语法: 禁用