第二十七章 DTrace

第二十七章 DTrace27.1. 简介27.2. 实施差异27.3. 启用DTrace支持27.4. 在Out-of-Kernel模块中启用DTrace27.5. 使用DTrace

27.1. 简介

DTrace,也称为动态跟踪,由Sun™开发,作为定位生产和预生产系统中性能瓶颈的工具。除了诊断性能问题外,DTrace还可以用于帮助调查和调试FreeBSD内核和用户区程序中的意外行为。

DTrace是一个出色的分析工具,具有诊断系统问题的一系列令人印象深刻的功能。它还可以用于运行预先编写的脚本,以利用其功能。用户可以使用DTrace D语言编写自己的实用程序,允许他们根据特定需求自定义分析。

FreeBSD实现提供了对内核DTrace的全面支持,以及对用户区DTrace的实验性支持。Userland DTrace允许用户使用 pid 提供程序对用户区程序执行函数边界跟踪,并将静态探测插入用户区程序以供以后跟踪。一些端口,如 databases/postgresql12-serverlang/php74 ,有一个DTrace选项来启用静态探测。

DTrace的官方指南由illumos Dynamic Tracing guide的illumos项目维护。

阅读本章后,你会知道:

• DTrace是什么以及它提供了哪些功能。 • Solaris™DTrace实现与FreeBSD提供的实现之间的差异。 • 如何在FreeBSD上启用和使用DTrace。

在阅读本章之前,您应该:

• 了解UNIX®和FreeBSD基础知识(FreeBSD基础知识)。 • 熟悉安全性以及它与FreeBSD(安全)的关系。

27.2. 实施差异

虽然FreeBSD中的DTrace与Solaris™中的DTrace相似,但确实存在差异。主要区别在于,在FreeBSD中,DTrace是作为一组内核模块实现的,在加载模块之前不能使用DTrace。要加载所有必要的模块:

从FreeBSD 10.0-RELEASE开始,当运行 dtrace(1) 时,模块会自动加载。

FreeBSD使用 DDB_CTF 内核选项来支持从内核模块和内核本身加载 ctf(5) 数据。CTF是Solaris™Compact C Type Format,它封装了一种简化形式的调试信息,类似于 DWARF 和古老的stabs。CTF 数据由 ctfconvert(1)ctfmerge(1) 构建工具添加到二进制文件中。 ctfconvert 实用程序解析编译器创建的 DWARF ELF 调试部分, ctfmerge 将对象中的 CTF ELF 部分合并到可执行文件或共享库中。

FreeBSD与Solaris™存在一些不同的提供商。最值得注意的是 dtmalloc 提供程序,它允许在FreeBSD内核中按类型跟踪 malloc(9) 。Solaris™中的一些提供程序,如 cpc ,在FreeBSD中不存在。这些可能会出现在FreeBSD的未来版本中。此外,这两个操作系统中可用的一些提供程序是不兼容的,因为它们的探测器具有不同的参数类型。因此,在Solaris™上编写的 D 脚本可能在FreeBSD上不可修改地工作,反之亦然。

由于安全差异,只有 root 可以在FreeBSD上使用DTrace。Solaris™有一些FreeBSD中尚不存在的低级安全检查。因此,/dev/dtrace/dtrace 被严格限制为 root 用户。

DTrace属于通用开发和分发许可证(Common Development and Distribution License,CDDL)许可证。要在FreeBSD上查看此许可证,请参阅 /usr/src/cddl/contrib/opensolaris/OPENSOLARIS.LICENSE 或在线查看 http://opensource.org/licenses/CDDL-1.0 。虽然支持DTrace的FreeBSD内核是 BSD 许可的,但当模块以二进制形式分发或加载二进制文件时,会使用 CDDL

27.3. 启用DTrace支持

在FreeBSD 9.2和10.0中,DTrace支持内置于GENERIC内核中。FreeBSD早期版本的用户或更喜欢在DTrace支持中静态编译的用户应将以下行添加到自定义内核配置文件中,并使用【10. 配置FreeBSD内核】中的说明重新编译内核:

AMD64架构的用户还应添加以下行:

此选项提供对 dtrace_fbt(4) 的支持。虽然DTrace可以在没有此选项的情况下工作,但对函数边界跟踪的支持有限。

一旦FreeBSD系统重新启动到新内核中,或者使用 kldload dtraceall 加载了DTrace内核模块,请安装当前的DTrace Toolkit(sysutils/dtrace-toolkit),这是一组用于收集系统信息的现成脚本。有脚本可以检查打开的文件、内存、CPU使用率等等。FreeBSD在基础系统中也包含了一些脚本;请参阅 /usr/share/dtrace

DTrace工具包包含许多DTrace特殊语言的脚本。这种语言被称为D语言,它与C++非常相似。对语言的深入讨论超出了本文的范围。有关FreeBSD上d语言的概述,请参阅FreeBSD d(7) 手册页。《illumos动态跟踪指南》中也广泛介绍了D语言。

27.4. 在Out-of-Kernel模块中启用DTrace

要将DTrace支持添加到内核外模块(Out-of-Kernel module)中,这对开发和调试很有用,请在模块的Makefile中包含以下行:

此标志在编译期间启用DTrace挂钩(hooks),允许对模块进行高级调试和监控。确保在此修改后重新编译模块以激活DTrace功能。

27.5. 使用DTrace

DTrace脚本由一个或多个探测或检测点的列表组成,其中每个探测都与一个操作相关联。只要满足探测条件,就会执行相关操作。例如,当打开文件、启动进程或执行一行代码时,可能会发生操作。操作可能是记录一些信息或修改上下文变量。上下文变量的读写允许探测器共享信息,并协同分析不同事件的相关性。

要查看所有探测器,管理员可以执行以下命令:

每个探测器都有一个 ID 、一个 PROVIDER(例如 dtracefbt )、一个 MODULE 和一个 FUNCTION NAME 。有关此命令的更多信息,请参阅 dtrace(1)

本节中的示例概述了如何使用DTrace Toolkit中两个完全支持的脚本:hotkernelprocsystem 脚本。

hotkernel 脚本旨在识别哪个函数使用了最多的内核时间。它将产生类似于以下内容的输出:

按照指示,使用 Ctrl+C 组合键停止该过程。终止后,脚本将显示内核函数和定时信息的列表,按时间升序对输出进行排序:

此脚本也适用于内核模块。要使用此功能,请使用 -m 运行脚本:

procsystemtime 脚本捕获并打印给定进程 IDPID)或进程名称的系统调用时间使用情况。在下面的示例中,生成了 /bin/csh 的新实例。然后,procsystime 被执行并保持等待,同时在 csh 的另一个化身上键入一些命令。以下是本次测试的结果:

如图所示, read(2) 系统调用使用了最多的时间(以纳秒为单位),而 getpid(2) 的系统调用使用的时间最少。