Solaris 动态跟踪指南

第 39 章 稳定性

Sun 通常会向开发者提前提供一些新技术及观察工具,从而使用户可以深入了解用户软件及内核软件的内部实现详细信息。但是,在软件进行升级或修补后,随着接口和实现的演变及成熟,新技术和内部实现详细信息也会随之发生变化。Sun 使用一组标签(在 attributes(5) 手册页中说明)来记录应用程序和接口的稳定性级别,以帮助用户设置对各种将来发行版中可能出现的更改类型的期望值。

没有一种稳定性属性可正确描述通过 D 程序访问的任意实体和服务集。因此,在 DTrace 和 D 编译器中,包含了可动态计算并描述所创建的 D 程序稳定性级别的功能。本章介绍用于确定程序稳定性的 DTrace 功能,以帮助您设计稳定的 D 程序。可以使用 DTrace 稳定性功能来通知您有关 D 程序的稳定性属性,或在程序具有不需要的接口相关性时生成编译时错误。

稳定性级别

DTrace 为内置变量、函数和探测器等实体提供了两类稳定性属性:稳定性级别和体系结构相关性类。其中,DTrace 稳定性级别通过指示在将来的发行版或修补程序中更改接口或 DTrace 实体的可能性,帮助您在基于 DTrace 开发脚本和工具时进行风险评估。DTrace 相关性类则向您指示某接口是否为所有 Solaris 平台和处理器公用,或该接口是否仅与特定的体系结构(如 SPARC 处理器)关联。用于描述接口的这两类属性可以独立变化。

下表按稳定性从低到高的顺序显示了 DTrace 使用的稳定性值。由于 Sun 将尽力确保在将来的次发行版中继续使用这些接口,因此可供所有 D 程序和分层应用程序使用的接口将更稳定。在将来的次发行版中,仅依赖稳定接口的应用程序将继续可靠地正常工作,并且不会被临时的修补程序破坏。使用稳定性较低的接口,可在当前系统上进行实验、设计原型、调节和调试,但是,使用时应认识到这些接口可能会出现不兼容的情况,甚至在将来的次发行版中可能被删除或替换。

另外,DTrace 稳定性值还有助于您了解所观察的软件实体的稳定性,以及 DTrace 接口本身的稳定性。因此,在升级或更改所观察的软件栈时,通过 DTrace 稳定性值,还可指示 D 程序和分层工具需要进行相应更改的可能性。

内部

该接口为 DTrace 专用,代表 DTrace 的实现详细信息。在次发行版或微发行版中,内部接口可能会有所变化。

专用

该接口为 Sun 专用,代表为供其他 Sun 产品(尚未公开发布以供用户和 ISV 使用的产品)使用而开发的接口。在次发行版或微发行版中,专用接口可能会有所变化。

过时

当前发行版支持该接口,但计划在将来的次发行版中将其删除。停止接口支持之前,Sun 将会首先尝试提供通知,然后再停止相应接口。如果您试图使用已过时的接口,D 编译器可能会生成警告消息。

外部

该接口受 Sun 以外的实体控制。根据 Sun 的自行判断,Sun 可将此类接 口的更新版本和可能不兼容的版本作为任何发行版的一部分提供,这主要受其在控制实体中的可用性限制。Sun 没有就任何两个发行版之间的外部接口的源或二进制兼容性进行任何声明。在将来的发行版中,基于这些接口的应用程序(包括包含外部接口的修补程序)可能无法运行。

不稳定

提供该接口的目的是为了使开发者能够预先体验新兴的、快速变化的技术,或预先体验对于观察或调试系统行为而言非常关键的实现产物,以便将来可采用一种更稳定的解决方案。Sun 没有就次发行版之间的不稳定接口的源或二进制兼容性进行任何声明。

发展中

该接口最终可能会成为标准接口或稳定接口,但现在仍处于转换状态。Sun 将会竭尽全力确保其在演变过程中与以前的发行版保持兼容。如果必须进行非向上兼容更改,这些更改将会在次发行版和主发行版完成。如有可能,应尽量避免在微发行版中进行这些更改。如果必须进行此类更改,应在受影响的发行版的发行说明中予以记录,并且 Sun 将在可行的情况下,为二进制兼容性和后续的 D 程序开发提供迁移帮助。

稳定

该接口是一个受 Sun 控制的成熟接口。Sun 将尽力避免对这类接口进行非向上兼容更改,尤其是在次发行版或微发行版中。如果必须停止对稳定接口的支持,Sun 将会尝试提供通知并将稳定性级别更改为“过时”。

标准

该接口符合行业标准。与该接口对应的文档将对该接口所符合的标准进行描述。这些标准通常由标准开发组织进行控制,可以依据对标准已批准的更改对接口进行更改。该稳定性级别还适用于已采用(但缺少行业约定的正式标准)的接口。仅对指定版本的标准提供支持,并不保证对更高版本提供支持。如果标准开发组织同意对 Sun 决定支持的标准接口进行非向上兼容更改,Sun 将公布一个兼容性和迁移策略。

相关性类

由于 Solaris 和 DTrace 支持各种平台和处理器,因此 DTrace 还为接口设置了相关性类标签,用于指示接口是否为所有 Solaris 平台和处理器公用,或该接口是否与特定的系统体系结构关联。相关性类与以前描述的稳定性级别互不相关。例如,DTrace 接口可以为“稳定”,但仅在 SPARC 微处理器中受支持,或者为“不稳定”,但为所有 Solaris 系统公用。在以下列表中,按最不常用(即完全特定于特定的体系结构)至最常用(即为所有体系结构公用)的顺序,介绍了各种 DTrace 相关性类。

未知

该接口具有未知的体系结构相关性集合。DTrace 不必了解所有实体(如操作系统实现中定义的数据类型)的体系结构相关性。未知标签通常适用于无法计算相关性且稳定性极低的接口。在当前使用的体系结构以外的任何体系结构上使用 DTrace 时,可能无法使用该接口。

CPU

该接口特定于当前系统的 CPU 型号。您可以使用 psrinfo(1M) 实用程序的 -v 选项显示当前的 CPU 型号和实现名称。具有 CPU 型号相关性的接口在其他 CPU 实现中可能不可用,即使这些 CPU 导出的指令集体系结构 (instruction set architecture, ISA) 相同。例如,尽管 UltraSPARC-III+ 微处理器和 UltraSPARC-II 微处理器都支持 SPARC 指令集,但前者的 CPU 相关接口在后者中可能不可用。

平台

该接口特定于当前系统的硬件平台。通常,平台将一组系统组件及体系结构特征(如一组支持的 CPU 型号)与系统名(如 SUNW,Ultra-Enterprise-10000)关联。您可以使用 uname(1) -i 选项显示当前的平台名称。该接口在其他硬件平台上可能不可用。

该接口特定于当前系统的硬件平台组。通常,平台组使用 sun4u 之类的单一名称,将具有相关特征的一组平台关联在一起。您可以使用 uname(1) - m 选项显示当前平台组名称。该接口在平台组中的其他平台上可用,但在不属于该组成员的硬件平台上可能不可用。

ISA

该接口特定于此系统中的微处理器支持的指令集体系结构 (instruction set architecture, ISA)。ISA 介绍了可在微处理器上执行的软件的规范,包括汇编语言指令和寄存器等详细信息。您可以使用 isainfo(1) 实用程序显示系统支持的本机指令集。在不会导出任何相同指令集的系统上,可能不支持该接口。例如,在 Solaris x86 系统上,可能不支持 Solaris SPARC 系统中的 ISA 相关接口。

公用

无论底层硬件如何,该接口均为所有 Solaris 系统公用。在具有相同 Solaris 和 DTrace 修订的其他 Solaris 系统上,可以执行和部署仅依赖公用接口的 DTrace 程序和分层应用程序。大多数 DTrace 接口均为公用接口,因此可在使用 Solaris 的任何地方使用它们。

接口属性

DTrace 使用由两个稳定性级别和一个相关性类组成的三重属性来描述接口。根据约定,接口属性按以下顺序列出,并用斜杠分隔:

name-stability /  data-stability / dependency-class

当接口名称显示在 D 程序中或 dtrace(1M) 命令行上时,接口的 name stability 描述与其名称关联的稳定性级别。例如,execname D 变量是一个“稳定”名称:根据以上介绍的稳定接口规则,Sun 保证在 D 程序中继续支持该标识符。

接口的 data stability 不同于与接口名称关联的稳定性。此稳定性级别说明,Sun 承诺维护接口以及任何关联的数据语义使用的数据格式。例如,pid D 变量是一个“稳定”接口:在 Solaris 中,进程 ID 是一个“稳定”概念。Sun 保证 pid 变量的类型将为 pid_t,并具有如下语义:根据稳定接口规则,将其设置为与触发给定探测器的线程对应的进程 ID。

接口的 dependency class 与其名称和数据稳定性均不同,用于说明接口是否特定于当前操作平台或微处理器。

我们将很快看到,DTrace 和 D 编译器可跟踪所有 DTrace 接口实体的稳定性属性,包括提供器、探测器说明、D 变量、D 函数、类型和程序语句本身。请注意,这三个值均能独立变化。例如,curthread D 变量具有“稳定/专用/公用”等属性:变量名称为“稳定”并且为所有 Solaris 操作平台“公用”,但该变量提供对作为 Solaris 内核实现产物的“专用”数据格式的访问。与所定义的变量相同,大多数 D 变量都提供“稳定/稳定/公用”等属性。

稳定性计算和报告

D 编译器可对 D 程序中的所有探测器说明和操作语句进行稳定性计算。您可以使用 dtrace -v 选项显示程序的稳定性报告。以下示例使用在命令行上编写的程序:


# dtrace -v -n dtrace:::BEGIN'{exit(0);}'
dtrace: description 'dtrace:::BEGIN' matched 1 probe
Stability data for description dtrace:::BEGIN:
        Minimum probe description attributes
                Identifier Names: Evolving
                Data Semantics:   Evolving
                Dependency Class: Common
        Minimum probe statement attributes
                Identifier Names: Stable
                Data Semantics:   Stable
                Dependency Class: Common
CPU     ID                    FUNCTION:NAME
  0      1                           :BEGIN

您可能还希望将 dtrace -v 选项与 -e 选项进行组合,以指示 dtrace 编译但不执行 D 程序,从而在不必启用任何探测器并执行程序的情况下确定程序稳定性。以下为另一个稳定性报告示例:


# dtrace -ev -n dtrace:::BEGIN'{trace(curthread->t_procp);}'
Stability data for description dtrace:::BEGIN:
        Minimum probe description attributes
                Identifier Names: Evolving
                Data Semantics:   Evolving
                Dependency Class: Common
        Minimum probe statement attributes
                Identifier Names: Stable
                Data Semantics:   Private
                Dependency Class: Common
#

请注意,在新程序中,我们引用了 D 变量 curthread,该变量具有“稳定”名称和“专用”数据语义(即如果您查看该语义,将访问内核的专用实现详细信息),并且此状态现在显示在程序的稳定性报告中。在程序报告中,通过从每个接口的三重属性的对应值中,选择最低稳定性级别和类计算稳定性属性。

对于探测器说明,可根据提供器发布的属性,通过为所有指定的探测器说明字段选择最低稳定性属性来计算稳定性属性。在与各提供器对应的章节中,显示了可用的 DTrace 提供器的属性。对于 DTrace 提供器发布的所有探测器,该提供器可导出四个说明字段中每一个字段的三重稳定性属性。因此,提供器名称的稳定性可能高于所导出的各个探测器的稳定性。例如,探测器说明:

fbt:::

指示 DTrace 应跟踪项并从所有内核函数返回,其稳定性高于以下探测器说明:

fbt:foo:bar:entry

该说明指定了内核模块 foo 中的特定内部函数 bar()。为简单起见,大多数提供器都使用一组属性来描述其发布的所有单个 module:function :name 的值。另外,提供器还会为 args[] 数组指定属性,因为所有探测器参数的稳定性都视提供器而定。

如果探测器说明中没有指定提供器字段,则为其指定“不稳定/不稳定/公用”的稳定性属性,因为该说明可能无法与在 Solaris 将来版本中使用时尚不存在的提供器的探测器匹配。同样,Sun 无法保证该程序将来的稳定性和行为。编写 D 程序子句时,应始终显式指定提供器。另外,包含模式匹配字符(请参见第 4 章)或 $1 等宏变量(请参见第 15 章)的任何探测器说明字段,将被视为未指定,因为这些说明模式可能会进行扩展,以便与 Sun 在将来版本的 DTrace 和 Solaris OS 中发布的提供器或探测器匹配。

对于大多数 D 语言语句,通过在语句中为实体选择最低稳定性和类来计算稳定性属性。例如,下列 D 语言实体具有如下属性:

实体 

属性 

内置的 D 变量 curthread

稳定/专用/公用 

用户定义的 D 变量 x

稳定/稳定/公用 

如果编写以下 D 程序语句:

x += curthread->t_pri;

则产生的语句属性为“稳定/专用/公用”,该最低属性与操作数 curthreadx 关联。表达式的稳定性通过为各操作数选择最低稳定性属性进行计算。

会自动为程序中定义的任何 D 变量指定“稳定/稳定/公用”属性。另外,会为 D 语言语法和 D 运算符隐式指定“稳定/稳定/公用”属性。对于使用反引号 (`) 运算符引用内核符号,将始终为其指定“专用/专用/未知”属性,因为它们反映实现产物。在 D 程序源代码中定义的类型,尤其是与 C 和 D 类型名称空间关联的类型,将为其指定“稳定/稳定/公用”属性。在操作系统实现中定义的类型,以及其他类型的名称空间提供的类型,将为其指定“专用/专用/未知”属性。D 类型转换运算符生成的表达式的稳定性属性,为输入表达式属性和转换输出类型属性之间的较小者。

如果您使用 C 预处理程序来纳入 C 系统头文件,这些类型将与 C 类型名称空间关联,并会为其指定“稳定/稳定/公用”属性,因为 D 编译器除了假定您会负责这些声明外,没有其他选择。因此,如果您使用 C 预处理程序来纳入包含实现产物的头文件,则可能会在程序稳定性方面误导您自己。为确定合适的稳定性级别,应始终参阅与要纳入的头文件对应的文档。

稳定性执行

开发 DTrace 脚本或分层工具时,您可能希望确定稳定性问题的具体来源,或确保程序具有所需的稳定性属性。您可以使用 dtrace -x amin=attributes 选项,强制 D 编译器在任何属性计算产生的三重属性小于在命令行上指定的最小值时生成错误。以下示例使用 D 程序源代码片段说明了 -x amin 的用法。请注意,使用由 / 分隔的三个标签按正常顺序指定各属性。


# dtrace -x amin=Evolving/Evolving/Common \
    -ev -n dtrace:::BEGIN'{trace(curthread->t_procp);}'
dtrace: invalid probe specifier dtrace:::BEGIN{trace(curthread->t_procp);}: \
    in action list: attributes for scalar curthread (Stable/Private/Common) \
    are less than predefined minimum
#