从 DTrace 脚本调用 C 函数
Posted
技术标签:
【中文标题】从 DTrace 脚本调用 C 函数【英文标题】:Calling C function from DTrace scripts 【发布时间】:2010-02-02 12:35:21 【问题描述】: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 函数,以便在跟踪过程中对跟踪数据执行高级操作。
【问题讨论】:
【参考方案1】:DTrace 明确阻止您执行此类操作,原因与您无法在 D 中编写循环相同:如果您以任何方式、形状或形式将其搞砸,整个系统都会崩溃。当 D 探针触发时,您处于 KERNEL 模式,而不是用户态。让我引用“Linux内核模块编程指南”:
所以,你想写一个内核模块。你知道 C,你写过很多 正常程序作为进程运行,现在你想要到达真正的地方 行动是,一个单一的野指针可以清除你的文件系统和一个 核心转储意味着重新启动。
这就是为什么你不想在 D 调查中扮演牛仔,以及为什么 D 的限制对你有好处。 =]
【讨论】:
【参考方案2】:您应该能够在每次使用管道触发探针后至少过滤 dtrace 的输出。
sudo dtrace -n 'proc:::exec-success trace(curpsinfo->pr_psargs); ' | perl myscript.plmyscript.pl:
#!/usr/bin/perl 而() 打印 $_; print "另一个应用程序启动了,做点什么!";
【讨论】:
【参考方案3】:由于@Sniggerfardimungus 提到的原因,不可能从探针内部调用任意 C,但大概您只想对正在收集的数据进行一些操作(将其存储在数据库中/进行一些计算或可视化使用它/等),这完全可以从 C 语言(以及通过其他几种语言中的 C 语言的包装器)实现。
为此,请使用libdtrace
(标头在我的Mac OS X 机器上的/usr/include/dtrace.h
)或它的包装器,例如node-libdtrace。基本思想是您可以构建自己的 DTrace 数据使用者(实际上,替换dtrace(1m)
命令行工具),它接收来自任何正在运行的脚本的输出。一旦你有了数据,你就可以用它做任何你想做的事情。
【讨论】:
【参考方案4】:编辑我的原始答案为时已晚,但您也可以在 DTrace 脚本中使用 system()
命令生成一个子进程,该子进程在 DTrace 中发生事件时运行任意代码。这可能是destructive action,因此您必须在 D 脚本中使用-w
命令行选项或#pragma D option destructive
指令。请注意,如果您不小心使用,破坏性操作可能会挂起、无限循环、杀死或以其他方式破坏您正在探测的进程。 (而且我不建议使用内核破坏性操作,除非您真的不在乎您的系统是否会因意外弄乱而崩溃。)
您可以使用 system()
运行的脚本来调用您的任意 C 代码(或向另一个进程发送信号以调用它等)。
【讨论】:
以上是关于从 DTrace 脚本调用 C 函数的主要内容,如果未能解决你的问题,请参考以下文章