3

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

4 回答 4

6

DTracey 显式阻止您执行此类操作,原因与您无法在 D 中编写循环相同:如果您以任何方式、形状或形式将其搞砸,整个系统都会崩溃。当 D 探针触发时,您处于 KERNEL 模式,而不是用户态。让我引用“Linux内核模块编程指南”:

所以,你想写一个内核模块。你知道 C,你已经编写了许多作为进程运行的普通程序,现在你想知道真正的动作在哪里,一个野指针可以清除你的文件系统,核心转储意味着重新启动.

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

于 2010-04-27T20:45:11.957 回答
1

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

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

myscript.pl:

#!/usr/bin/perl
而(<>){
打印 $_;
print "另一个应用程序启动了,做点什么!";
}

于 2010-04-28T05:30:25.683 回答
1

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

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

于 2013-12-16T22:35:12.437 回答
1

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

为此,请使用libdtrace(标题在/usr/include/dtrace.h我的 Mac OS X 机器上)或它的包装器,例如node-libdtrace。基本思想是您可以构建自己的 DTrace 数据使用者(实际上是替换dtrace(1m)命令行工具),它接收来自正在运行的任何脚本的输出。一旦你有了数据,你就可以用它做任何你想做的事情。

于 2013-05-29T23:23:18.340 回答