Solaris 动态跟踪指南

提供器和探测器

在前面的示例中,您学习了如何使用两个简单的、名为 BEGINEND 的探测器。但是,这些探测器来自何处呢?DTrace 探测器来自一组称为提供器的内核模块,其中,每个模块都执行一种特定类型的检测过程来创建探测器。使用 DTrace 时,每个提供器均有机会将可提供的探测器发布到 DTrace 框架。然后,您可以启用并将跟踪操作绑定到已发布的任何探测器。要列出系统中的所有可用探测器,请键入以下命令:


# dtrace -l
  ID   PROVIDER            MODULE          FUNCTION NAME
   1     dtrace                                     BEGIN
   2     dtrace                                     END
   3     dtrace                                     ERROR
   4   lockstat           genunix       mutex_enter adaptive-acquire
   5   lockstat           genunix       mutex_enter adaptive-block
   6   lockstat           genunix       mutex_enter adaptive-spin
   7   lockstat           genunix       mutex_exit  adaptive-release

   ... many lines of output omitted ...

#

显示所有输出可能需要一些时间。要统计所有探测器的数量,可以键入以下命令:


# dtrace -l | wc -l
        30122

您可能会注意到您的计算机中的探测器总数有所不同,这是因为探测器的数量因操作平台及所安装的软件而异。如您所见,有大量的探测器可供您使用,因此,您可以检查系统中以前未曾关注过的的每个位置。事实上,如您随后将了解到的,即使此输出列表也是不完整的,因为某些提供器可基于跟踪请求动态创建新的探测器,从而导致 DTrace 探测器的实际数量是无限。

现在,我们返回来在终端窗口中查看 dtrace -l 的输出。请注意先前已经提到过的,每个探测器都有两个名称,一个整数 ID 以及一个人工可读的名称。人工可读的名称包括四个部分,如 dtrace 输出中的各列所示。探测器名称的四个部分如下:

提供器 

发布此探测器的 DTrace 提供器的名称。提供器名称通常与执行检测过程以启用探测器的 DTrace 内核模块的名称相对应。 

模块 

此探测器对应于特定的程序位置时,为探测器所在模块的名称。该名称为内核模块的名称或用户库的名称。 

功能 

此探测器对应于特定的程序位置时,为探测器所在程序函数的名称。 

名称 

探测器名称的最后组成部分是一个有助于您了解探测器语义的名称(如 BEGINEND)。

写出完整的人工可读的探测器名称时,请用冒号分隔列出该名称的所有四个部分,如下所示:

提供器:模块:函数:名称

请注意,该列表中某些探测器没有模块和函数,如先前使用的 BEGINEND 探测器。某些探测器将这两个字段留为空白,这是因为这些探测器与任何特定的受检测程序函数或位置都不对应。相反,这些探测器是指一个更抽象的概念,如跟踪请求结束。将模块和函数作为其名称一部分的探测器称为固定探测器,名称中没有模板和函数的探测器则称为不固定探测器

根据约定,如果没有指定探测器名称的所有字段,则只要探测器中的值与您指定的那部分名称相匹配,DTrace 就会将您的请求与所有此类探测器匹配。换而言之,在先前使用探测器名称 BEGIN 时,您实际上是指示 DTrace 匹配名称字段为 BEGIN 的任何探测器,而不考虑提供器、模块和函数字段的具体值。由于恰好只有一个探测器与该描述相符,因此才出现相同的结果。但是,您现在知道 BEGIN 探测器的实际名称为 dtrace:::BEGIN,这表示该探测器由 DTrace 框架本身提供,并且不固定到任何函数。因此,如果按以下所示方式编写 hello.d 程序,则也会生成相同结果:

dtrace:::BEGIN
{
	trace("hello, world");
	exit(0);
}

至此,您已了解探测器的来源和命名方式,接下来我们将进一步了解启用探测器并要求 DTrace 执行某些操作时发生的情况,然后我们会返回到 D 程序旋风之旅。