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函数,以便在跟踪过程中使用该跟踪数据执行高级操作。
答案 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代码(或向另一个进程发送信号以调用它等)。