Dtrace

DTrace(全称Dynamic Tracing),也称为动态跟踪,是由 Sun™ 开发的一个用来在生产和试验性生产系统上找出系统瓶颈的工具,可以对内核(kernel)和用户应用程序(user application)进行动态跟踪并且对系统运行不构成任何危险的技术。在任何情况下它都不是一个调试工具,而是一个实时系统分析寻找出性能及其他问题的工具。 DTrace 是个特别好的分析工具,带有大量的帮助诊断系统问题的特性。还可以使用预先写好的脚本利用它的功能。 用户也可以通过使用 DTrace D 语言创建他们自己定制的分析工具, 以满足特定的需求。

Oracle Linux可以支持Dtrace

在 Oracle Linux 上使用 DTrace 的一些优点是您可以:

l  观察整个软件体系、操作系统内核、系统库和应用程序的动态运行时性能。

l  通过在运行时定义实时探测点识别性能瓶颈。

l  开发探测器在谓词控制下触发时执行的脚本。

l  检测并报告内存访问错误,而不是听任系统崩溃。

DTrace针对 Oracle Linux Unbreakable Enterprise Kernel 的移植是一项仍在不断发展的技术。其目标是为动态跟踪提供集成解决方案,最终与 Oracle Solaris 功能兼容,同时为 Oracle Linux 带来新特性。

使用概述

要使用 DTrace,需要指定内核中感兴趣的位置(称为探测器),其中 DTrace 可以绑定一个请求来执行一组操作,如记录堆栈跟踪、时间戳或函数参数。探测器的作用类似于深埋于操作系统中用于记录信息的可编程遥感传感器。探测器触发时,DTrace 会从其收集数据并向您回报数据。Oracle Linux DTrace 探测器运行于被称作提供程序的 DTrace 内核模块中,提供程序执行插装以支持探测器。

DTrace 可安全用于生产系统,无需重启系统或运行任何应用程序。可以通过 dtrace(1) 命令或 DTrace D 脚本语言调用运行时跟踪。无论采用哪种方式,都可以查询系统探测器,针对设计的任意问题提供即时、准确的答案。

命令行 dtrace 调用,指定调用 open() 系统调用的命令以及被打开的文件的名称(在控制台登录过程中):

#dtrace -q -n syscall::open:entry'{ printf("%-16s%-16s\n",execname,copyinstr(arg0)); }'

是在运行的系统上实时发生的。按 Ctrl + C 可终止跟踪。

DTrace脚本语言 D 专为动态跟踪而设计。使用 D 脚本,可以动态启用探测器、收集数据和处理数据。D 脚本可与其他人共享,Oracle 技术网上发布了许多 D 脚本。

调用 D 语言脚本 syscalls.d 显示进程 5178 正在使用的系统调用及其频率:

# catsyscalls.d

#!/usr/sbin/dtrace-qs

syscall:::entry

/pid== $1/

{

  @num[probefunc] = count();

}

探测器和提供程序

DTrace 探测器来自一组被称作提供程序的内核模块,每个提供程序执行特定类型的插装来创建探测器。使用 DTrace 时,每个提供程序都有机会发布它可以为 DTrace 框架提供的探测器。然后,您可以对已发布的任何探测器启用和绑定跟踪操作。

要列出系统上的所有可用探测器,请键入

#dtrace -l

系统上的清单可能与此不同,因为根据 Oracle Linux 平台、安装的软件和加载的提供程序模块的不同,探测器的数量也不同。

每个探测器都显示一个整数 ID 和一个易于理解的名称,由四部分组成,在 dtrace 输出中显示为单独的四列。

l  provider — 发布此探测器的 DTrace 提供程序的名称。提供程序名称通常对应于执行插装以启用探测器的 DTrace 内核模块的名称。

l  module — 如果此探测器对应于特定程序位置,则为探测器所在内核模块的名称。

l  function — 如果此探测器对应于特定程序位置,则为探测器所在程序函数的名称。

l  name — 探测器名称的最后一部分,即表明探测器语义的名称。

当提及具体探测器时,这些部分一起显示,中间用冒号分隔,如:

provider:module:function:name

如下所示提供程序在 Oracle Linux 上的当前 DTrace 实现中可用。

l  dtrace dtrace 为 DTrace 本身提供探测器:BEGIN、END、ERROR,用于可选地在跟踪开始之前初始化 DTrace、执行跟踪后处理、处理执行期间其他探测器中的意外错误。

l  io io 提供与数据输入和输出有关的监视探测器。

l  proc proc 为监视进程创建和终止、新程序映像执行以及发送和处理信号提供探测器。

l  profile profile 提供与定时中断关联的探测器。可以使用这些探测器以固定时间间隔对系统状态进行采样。

l  sched sdt 提供与 CPU 调度有关的探测器。

l  sdt sdt 提供静态定义的、位于内核中多个感兴趣的重要位置的跟踪探测器。

l  syscall systrace 在每个系统调用的入口点和返回点提供探测器。这些探测器对了解应用程序与底层系统之间的交互尤为有用。

以下是几个例子。

进入 open() 系统调用:

syscall::open:entry

 

进入任何 open*() 系统调用,如 open64():

syscall::open*:entry

 

进入任意系统库调用:

syscall:::entry

 

syscall提供程序发布的所有调用:

syscall:::

Oracle Linux 和 Oracle Solaris 中 DTrace 之间的差异

Oracle Solaris 中的有些 DTrace 提供程序在 Oracle Linux 中尚未实现。

要列出一个具体提供程序发布的探测器,使用以下命令:

#dtrace -l -P provider

要验证探测器是否可用,使用以下命令:

#dtrace -l -n probe_name

dtrace(1)命令行

许多非常有用的跟踪都可以直接从 dtrace(1) 命令行运行。这些称为单行命令,许多都可以在相关文档和互联网上找到。

例如,单行命令执行定向内核堆栈跟踪:

#dtrace -n 'gettimeofday:entry {stack()}'

dtrace:description 'gettimeofday:entry' matched 1 probe

CPU ID0 196

0 196

下面列出几个重要的选项标志:

-ccommand — 运行指定命令,完成后退出。如果指定多个 -c 选项,dtrace 将在所有命令退出后退出,并在终止时报告每个子进程的退出状态。

-ffunction — 指定您想要跟踪或列出的函数(也可以指定提供程序和模块)。可以附加一个可选的 D 探测器子句。可以多次为命令指定 -f 选项。function 还可以采用此形式:[[provider:]module:]function[[predicate]action]。

-l — 列出探测器,而非启用探测器。dtrace 基于 -f、-i、-m、-n、-P 和 -s 选项的参数筛选探测器列表。如果未指定选项,dtrace 将列出所有探测器。

-mmodule — 指定您想要跟踪或列出的模块(也可以指定提供程序)。可以附加一个可选的 D探测器子句。可以多次为命令指定 -m 选项。module 还可以采用此形式:[[provider:]module [[predicate]action]]。

-nname —指定您想要跟踪或列出的探测器名称(也可以指定提供程序、模块和函数)。可以附加一个可选的 D 探测器子句。可以多次为命令指定 -n 选项。name 还可以采用此形式:[[provider:]module:]function:]name[[predicate]action]]。

-p PID—捕获由进程 ID 指定的进程,缓存其符号表,并在完成后退出。如果指定多个 -p 选项,dtrace 将在所有进程退出后退出,并在终止时报告每个子进程的退出状态。

-Pprovider — 指定您想要跟踪或列出的提供程序。可以附加一个可选的 D 探测器子句。可以多次为命令指定 -P 选项。provider 还可以采用此形式:provider['D- probe_clause']。

-ssourcefile — 编译指定的 D 程序源文件并开始跟踪。

谓词是用于有条件跟踪数据的 D 语言逻辑表达式。命令行中还可以出现以斜线 (//) 括起的谓词,D 语句的动作列表放在括号 ({ }) 中。(下一节谈到 D 语言时将详细介绍这一点。)但是,可选谓词和动作文本在命令行中使用时必须适当地用引号括起来,以免 shell 对其进行解释。在清单 4 中,-n 选项标志为以下形式:-n 'function:name{action}'。

下面是谓词的一些示例。

如果探测器在 cpu0 上执行,则为 true:

cpu ==0

如果触发探测器的进程 PID 为 1029,则为 true:

pid ==1029

如果进程不是调度程序 (sched),则为 true:

execname!= "sched"

如果父 PID 不为 0 且第一个参数为 0,则为 true:

ppid!= 0 && arg0 == 0

如果只想了解特定 CPU 上触发的特定探测器,而不跟踪任何数据或执行任何其他操作,可以指定一组内部无语句的空括号,DTrace 就会只打印触发的探测器的名称。

下面是操作的一些示例。

使用 C 语言式 printf() 命令打印内容:

printf()

打印用户级堆栈:

ustack()

打印给定变量:

trace

Logo

更多推荐