2010-02-02 60 views
3

DTrace是最初来自Solaris的令人印象深刻的强大的跟踪系统,但它被移植到FreeBSD和Mac OSX。从DTrace脚本调用C函数

DTrace的使用称为d高级语言没有什么不同AWK或C.下面是一个例子:

io:::start 
/pid == $1/ 
{ 
    printf("file %s offset %d size %d block %llu\n", args[2]->fi_pathname, 
     args[2]->fi_offset, args[0]->b_bcount, args[0]->b_blkno); 
} 

使用命令行sudo dtrace -q -s <name>.d <pid>所有IO源于该过程被记录下来。

我的问题是如何以及如何从DTrace脚本中调用自定义C函数,以便在跟踪过程中对跟踪数据执行高级操作。

回答

6

DTrace explicity阻止您做这样的事情,原因与您无法在D中编写循环的原因相同:如果以任何方式,形状或形式拧紧它,您会使整个系统崩溃。当D探头发射时,您处于KERNEL模式,而不是userland。让我引用“Linux内核模块编程指南”:

所以,你要编写一个内核模块。你知道C,你已经写了一些 正常程序作为进程运行,现在你想要到达真正的 动作的位置,一个野指针可以擦除你的文件系统,一个 核心转储意味着重启。

这就是为什么你不想在D探针中扮演牛仔,为什么D的限制对你有好处。 =]

1

您应该能够在每个探测器用管道触发后至少过滤dtrace的输出。

 
sudo dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }' | perl myscript.pl

myscript.pl:

#!/usr/bin/perl 
while (<>){ 
print $_; 
print "another application launched, do something!"; 
}

1

这是不可能从您的探测器为@Sniggerfardimungus提到的原因的内部调用任意C,但想必你只想做一些操作与同时是数据收集(将其存储在数据库中/使用它/进行一些计算或可视化),这完全有可能来自C(以及通过围绕几个其他语言的C的包装)。

要做到这一点,请使用libdtrace(标题在我的Mac OS X框中的/usr/include/dtrace.h)或其包装器(如node-libdtrace)。基本思想是您可以构建您自己的DTrace数据使用者(实际上替换dtrace(1m)命令行工具),该工具从正在运行的任何脚本接收输出。一旦你有了数据,你可以随心所欲地做任何事情。

1

编辑我原来的答案还不够,但您也可以在DTrace脚本中使用system()命令生成一个在DTrace中发生事件时运行任意代码的子流程。这是潜在的destructive action,所以您必须在D脚本中使用-w命令行选项或#pragma D option destructive指令。请注意,破坏性操作可能会挂起,无限循环,杀死并以其他方式破坏您正在探查的进程,如果您不仔细使用它们。 (我不会推荐使用内核的破坏性行为,除非你真的不在乎你的系统在意外搞砸时是否会关闭。)

你可以使用脚本运行system()来调用你的任意C代码或发送信号给另一个进程来调用它等)。