DTrace简介

12 篇文章 0 订阅
10 篇文章 0 订阅

基本语法

probe
/ optional predicates /
{
       optional action statements;
}

其中:

1)       probe:探针,即所要探查的对象。

2)       optional predicates :DTrace脚本没有if语句,使用/ optional predicates /来替代。

3)       optional action statements;:探针命中后执行的操作。

探针(probe)

provider:module:function:name

1)       provider: 某组探针的名字。例如:系统调用(syscall),用户函数调用(pid$target)。

2)       module: 模块名或库名。例如:libc.so,a.out。

3)       function: 函数名。例如:printf。

4)       name: 探针的组件名。例如:函数调用的入(entry)、出(return)。

四个部分一起来限定探针,如果某部分为空,则为匹配所有。

如果对不同探针的操作一样,则用逗号分隔探针,例:

pid$target:2::entry,
pid$target:2::return
{
 …
}

聚合函数

操作中可以使用聚合函数:

1)       count:当探针命中时+1

例,统计每个函数的调用次数:

#!/usr/sbin/dtrace -s
 
pid$target:2::entry
{
       @func[probefunc] = count();
}

2)       avg

3)       sum

4)       max

5)       min

6)       quantize:所指定表达式的值的二次方频数分布。递增最高二次方存储桶中小于所指定表达式的值。

7)       lquantize:与quantize的区别是,lquantize可以指定上下限、步长

变量

类型:

1)       关联数组

2)       标量:普通变量

作用范围:

1)       全局变量

2)       线程局部变量:有self->前缀的

3)       语句局部变量

操作

ustack(),显示用户函数的堆栈。例,显示调用void foo(const int)时的堆栈:

#!/usr/sbin/dtrace -qs
 
/* void foo(const int) = __1cDfoo6Fki_v_ */
pid$target:2:__1cDfoo6Fki_v_:entry
{
       ustack();
}

举例

运行这些例子需要额外权限,建议使用root用户。

一、显示调用函数的参数值

1)       1.cpp的内容如下:

void foo(const int i)
{
}
 
int main()
{
       foo(123456);
       return 0;
}

2)       编译1.cpp为1:

CC 1.cpp -o 1

3)       pargs.d的内容如下:

#!/usr/sbin/dtrace -qs
 
/*print foo and args, the function name is c++mangled*/
pid$target:1:__1cDfoo6Fki_v_:entry
{
        printf("%-15s:%8d\n", probefunc, arg0);
}

其中__1cDfoo6Fki_v_为void f(const int)经过mangle后的名称。

4)       运行程序和DTrace:

#./pargs.d-c ./1|c++filt

void foo(const int):   123456

注:

a) 如果是类函数,arg0是this指针,参数从arg1开始。

b) 用-c cmd这种方式,会设置$target宏。这时再用pid$target,就可以只显示cmd进程相关的trace。

c) 使用-p pid这种形式,也会设置$target宏。可以使用这种方法探查已运行的程序。

二、显示调用函数的返回值

1)       return.cpp的内容如下:

int foo(const int i)
{
       return 9876;
}
 
int main()
{
       foo(123456);
       return 0;
}
2)       编译return.cpp为return:

CC return.cpp -o return

3)       return.d的内容如下:

#!/usr/sbin/dtrace -qs
 
pid$target:return:__1cDfoo6Fki_i_:return
{
       printf("%-15s return: %8d\n", probefunc, arg1);
}

其中__1cDfoo6Fki_i_为int foo(const int i)经过mangle后的名称。

4)       运行程序和DTrace:

#./return.d -c ./return|c++filt

int foo(const int) return:     9876

注:对探针return,如果函数具有返回值,则该返回值存储在arg1中。如果函数不具有返回值,则不会定义arg1。

三、显示调用函数的参数值(类类型)

1)       ptr_arg.cpp的内容如下:

class A
{
public:
        inti;
        intj;
       virtual ~A(){}
};
 
int foo(const A& a)
{
       return 9876;
}
 
int main()
{
        Aa;
        a.i= 12345;
        a.j= 45678;
       foo(a);
       return 0;
}

2)       编译ptr_arg.cpp为ptr_arg:

CC ptr_arg.cpp-o ptr_arg

3)       ptr_arg.d的内容如下:

#!/usr/sbin/dtrace -qs
 
pid$target:ptr_arg:__1cDfoo6FrknBA__i_:entry
{
       printf("i: %8d\n", *(int*)(copyin(arg0 + sizeof(int),sizeof(int))));
       printf("j: %8d\n", *(int*)(copyin(arg0 + sizeof(int) +sizeof(int), sizeof(int))));
}

其中__1cDfoo6FrknBA__i_为int foo(const A& a)经过mangle后的名称。

4)       运行程序和DTrace:

#./ptr_arg.d -c ./ptr_arg|c++filt

i:   12345

j:   45678

注:

a) arg0为this指针的地址;

b) arg0+sizeof(int)为i的地址;

c) arg0+sizeof(int)+sizeof(int)为j的地址;

d) copyin的原型是:void *copyin(uintptr_t addr,size_t size)。它是将被测进程的数据复制到内核地址空间中,然后再对其进行解引用操作,就能知道数据的值是多少。

四、显示调用函数的参数值(string类型)

1)       ptr_str.cpp的内容如下:

#include <string>
 
using namespace std;
 
void foo(const string& s)
{
}
 
int main()
{
       string a = "saaab";
       foo(a);
       return 0;
}

2)       编译ptr_str.cpp为ptr_str:

CC ptr_str.cpp -o ptr_str

3)       ptr_str.d的内容如下:

#!/usr/sbin/dtrace -qs
 
pid$target:ptr_str:__1cDfoo6FrknDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____v_:entry
{
        str= *(int*)copyin(arg0, sizeof(int));
        printf("%s\n",copyinstr(str));
}

其中__1cDfoo6FrknDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____v_为void foo(const string& s)经过mangle后的名称。

4)       运行程序和DTrace:

#./ptr_str.d -c ./ptr_str|c++filt

saaab

五、统计调用函数的时间

1)       time.cpp的内容如下:

#include <unistd.h>
 
void foo()
{
       sleep(1);
}
 
void bar()
{
       sleep(2);
       foo();
}
 
int main()
{
       bar();
       return 0;
}

2)       编译time.cpp为time:

CC time.cpp -o time

3)       time.d的内容如下:

#!/usr/sbin/dtrace -qs
 
pid$target:time::entry
{
       start[probefunc] = timestamp;
}
 
pid$target:time::return
/start[probefunc]/
{
       @elapsed[probefunc] = sum(timestamp - start[probefunc]);
       self->start[probefunc] = 0;
}

timestamp的精度为纳秒(1秒等于1000000000纳秒)。

4)       运行程序和DTrace:

#./time.d -c ./time|c++filt

__ex_deregister_at_exit                                       22500

 __cplus_fini_at_exit                                        24000

 void foo()                                            1010022500

 void bar()                                           3018742700

 _start                                               3027984000

六、显示调用函数时的堆栈

1)       1.cpp的内容如下:

void foo(const int i)
{
}
 
int main()
{
       foo(123456);
       return 0;
}
 

2)       编译1.cpp为1:

CC 1.cpp -o 1

3)       ustack.d的内容如下:

#!/usr/sbin/dtrace -qs
 
pid$target:1:__1cDfoo6Fki_v_:entry
{
       ustack()
}

其中__1cDfoo6Fki_v_为void f(const int)经过mangle后的名称。

4)       运行程序和DTrace:

#./ ustack.d -c ./1|c++filt

              1`void foo(const int)

             1`main+0xc

              1`_start+0x108

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值