作为 dtrace4linux 的作者,让我来回答一下。
本质上,Linux/MacOS/FreeBSD/Solaris 上的 dtrace 是相同的——我们都基于相同的源代码和相同的目标。因为没有中央维护者,代码实际上是分叉的,Solaris 被认为是主控。主要的源代码差异是每个平台的粘合剂。
DTrace 是多种事物的组合:
- 内核驱动程序
- 用户空间“dtrace”命令
- 探测功能机制(例如 syscall、fbt)
- 脚本语言
看看系统调用跟踪它非常简单:
$ dtrace -n syscall::open:
.....
这会捕获每个打开的系统调用,无论是谁执行的。如果您了解 Unix,您就会知道系统调用大约是:
open(char *filename, int flags, [int perms])
因此,arg0 是字符串“文件名”。但这就是不同的地方。C lib 函数如上,但它映射到系统调用,类似于:
open(int someflags, char *filename, int userflags, int perms)
所以文件名不在 arg0 中,而是在 arg1 中。(如果以上有错误,我深表歉意——我认为open()
内核和用户空间是一样的,但事实并非如此,例如对于stat()
函数族)。
这就是 DTrace 的一些“可移植性”问题出现的地方——如果您使用 dtrace 的 Solaris 指南,并尝试运行一些脚本或示例,您可能会发现它们的工作方式不同。理论上,这是 Linux(我)的错,应该修改 dtrace4linux 来隐藏这个。
这一切都适用于系统调用。
现在让我们看看 fbt。Fbt 只是函数跟踪——任何函数——带有任何参数。您可以跟踪实现open()
系统调用的 linux 函数(它被称为sys_open
[可能])。如果您捕获此功能:
$ dtrace -n fbt::sys_open:
那么你必须查看内核源代码,看看arg0、arg1、arg2等是什么。几乎可以肯定它与 Solaris 或 MacOS 不同——其 Linux 的实现细节。
但是您可能想要访问一些参数,例如获取一些内部内核数据结构(TCP、磁盘驱动程序、USB 驱动程序等)。Solaris 提供了“提供者”,它们是访问数据结构的更高级别的方法,而不是知道“arg3 是'struct foo *'”。如果没有这些提供程序,脚本将完全依赖于 opsys,并且没有可移植性。大多数人并不关心“tcp”结构是什么样子,而是希望访问诸如 pktin、pktout、rcvbytes、sndbytes 之类的关键字段。
总之dtrace4linux
,Solarisdtrace
提供了一个可移植层来允许访问这些功能或结构,但 dtrace4linux 或 Solaris 都没有尝试完成一项完整的工作来提供跨每个内核中数千个结构的可移植性。
通常,您可以使用 solaris 教程脚本并使用它们来尝试了解哪些不起作用,但是如果您不知道要查找什么,则尝试“按原样”使用它们会使您感到沮丧。
我认为 dtrace4linux 是“不错”和“不够好”来隐藏这些差异。(dtrace4linux 与 MacOS 差不多——如果您使用 Solaris 教程,有些教程可能无法在 Mac 或 FreeBSD 上运行)。