从DTrace脚本调用C函数

时间:2010-02-02 12:35:22

标签: dtrace

DTrace是一个令人印象深刻,功能强大的跟踪系统,最初来自Solaris,但它被移植到FreeBSD和Mac OSX。

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函数,以便在跟踪过程中使用该跟踪数据执行高级操作。

4 个答案:

答案 0 :(得分:6)

DTrace explicity阻止你做这样的事情,原因与你不能在D中写一个循环的原因相同:如果你以任何方式,形状或形式搞砸了,你就会崩溃整个系统。当D探测器触发时,您处于KERNEL模式,而不是用户空间。让我引用“Linux内核模块编程指南:”

所以,你想编写一个内核模块。你知道C,你写了很多 正常程序作为进程运行,现在你想要到达真实的地方 动作是,一个狂野指针可以消灭你的文件系统和一个 核心转储意味着重启。

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

答案 1 :(得分: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!";
}

答案 2 :(得分:1)

由于@Sniggerfardimungus提到的原因,无法从探针内部调用任意C,但可能您只是想对正在收集的数据进行一些操作(将其存储在数据库中/进行一些计算或可视化)使用它/ etc),这完全可以从C(以及通过其他一些语言的C语言包装)。

要执行此操作,请使用libdtrace(标题位于我的Mac OS X框中的/usr/include/dtrace.h)或其node-libdtrace的包装。基本思想是,您可以构建自己的DTrace数据使用者(实际上,替换dtrace(1m)命令行工具),该工具从正在运行的任何脚本接收输出。获得数据后,您可以随心所欲地使用它。

答案 3 :(得分:1)

编辑原始答案太晚了,但您也可以使用DTrace脚本中的system()命令生成在DTrace中发生事件时运行任意代码的子进程。这可能是destructive action,因此您必须在D脚本中使用-w命令行选项或#pragma D option destructive指令。请注意,如果您不小心使用它们,破坏性操作可能会挂起,无限循环,终止并以其他方式破坏您正在探测的进程。 (我不建议使用内核破坏性操作,除非你真的不在意你的系统是否在意外搞乱时崩溃。)

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