放弃推理
第13 章• 推理跟踪175
推理示例
推理的一个可能用法是突出显示特定的代码路径。只有当open() 失败时,以下示例才在
open(2) 系统调用下显示整个代码路径:
示例13–1 specopen.d: 失败的open(2) 代码流
#!/usr/sbin/dtrace -Fs
syscall::open:entry,
syscall::open64:entry
{
/*
* The call to speculation() creates a new speculation. If this fails,
* dtrace(1M) will generate an error message indicating the reason for
* the failed speculation(), but subsequent speculative tracing will be
* silently discarded.
*/
self->spec = speculation();
speculate(self->spec);
/*
* Because this printf() follows the speculate(), it is being
* speculatively traced; it will only appear in the data buffer if the
* speculation is subsequently commited.
*/
printf("%s", stringof(copyinstr(arg0)));
}
推理示例
176 Solaris 动态跟踪指南• 2006 年7 月
示例13–1 specopen.d: 失败的open(2) 代码流(续)
fbt:::
/self->spec/
{
/*
* A speculate() with no other actions speculates the default action:
* tracing the EPID.
*/
speculate(self->spec);
}
syscall::open:return,
syscall::open64:return
/self->spec/
{
/*
* To balance the output with the -F option, we want to be sure that
* every entry has a matching return. Because we speculated the
* open entry above, we want to also speculate the open return.
* This is also a convenient time to trace the errno value.
*/
speculate(self->spec);
trace(errno);
推理示例
第13 章• 推理跟踪177
示例13–1 specopen.d: 失败的open(2) 代码流(续)
}
syscall::open:return,
syscall::open64:return
/self->spec && errno != 0/
{
/*
* If errno is non-zero, we want to commit the speculation.
*/
commit(self->spec);
self->spec = 0;
}
syscall::open:return,
syscall::open64:return
/self->spec && errno == 0/
{
/*
* If errno is not set, we discard the speculation.
*/
discard(self->spec);
self->spec = 0;
}
推理示例
178 Solaris 动态跟踪指南• 2006 年7 月
运行上面的脚本将会生成与以下示例类似的输出:
# ./specopen.d
dtrace: script ’./specopen.d’ matched 24282 probes
CPU FUNCTION
1 => open /var/ld/ld.config
1 -> open
1 -> copen
1 -> falloc
1 -> ufalloc
1 -> fd_find
1 -> mutex_owned
1 <- mutex_owned
1 <- fd_find
1 -> fd_reserve
1 -> mutex_owned
1 <- mutex_owned
1 -> mutex_owned
1 <- mutex_owned
1 <- fd_reserve
1 <- ufalloc
1 -> kmem_cache_alloc
1 -> kmem_cache_alloc_debug
1 -> verify_and_copy_pattern
1 <- verify_and_copy_pattern
推理示例
第13 章• 推理跟踪179
1 -> file_cache_constructor
1 -> mutex_init
1 <- mutex_init
1 <- file_cache_constructor
1 -> tsc_gethrtime
1 <- tsc_gethrtime
1 -> getpcstack
1 <- getpcstack
1 -> kmem_log_enter
1 <- kmem_log_enter
1 <- kmem_cache_alloc_debug
1 <- kmem_cache_alloc
1 -> crhold
1 <- crhold
1 <- falloc
1 -> vn_openat
1 -> lookupnameat
1 -> copyinstr
1 <- copyinstr
1 -> lookuppnat
1 -> lookuppnvp
1 -> pn_fixslash
1 <- pn_fixslash
1 -> pn_getcomponent
推理示例
180 Solaris 动态跟踪指南• 2006 年7 月
1 <- pn_getcomponent
1 -> ufs_lookup
1 -> dnlc_lookup
1 -> bcmp
1 <- bcmp
1 <- dnlc_lookup
1 -> ufs_iaccess
1 -> crgetuid
1 <- crgetuid
1 -> groupmember
1 -> supgroupmember
1 <- supgroupmember
1 <- groupmember
1 <- ufs_iaccess
1 <- ufs_lookup
1 -> vn_rele
1 <- vn_rele
1 -> pn_getcomponent
1 <- pn_getcomponent
1 -> ufs_lookup
1 -> dnlc_lookup
1 -> bcmp
1 <- bcmp
1 <- dnlc_lookup
推理示例
第13 章• 推理跟踪181
1 -> ufs_iaccess
1 -> crgetuid
1 <- crgetuid
1 <- ufs_iaccess
1 <- ufs_lookup
1 -> vn_rele
1 <- vn_rele
1 -> pn_getcomponent
1 <- pn_getcomponent
1 -> ufs_lookup
1 -> dnlc_lookup
1 -> bcmp
1 <- bcmp
1 <- dnlc_lookup
1 -> ufs_iaccess
1 -> crgetuid
1 <- crgetuid
1 <- ufs_iaccess
1 -> vn_rele
1 <- vn_rele
1 <- ufs_lookup
1 -> vn_rele
1 <- vn_rele
1 <- lookuppnvp
推理示例
182 Solaris 动态跟踪指南• 2006 年7 月
1 <- lookuppnat
1 <- lookupnameat
1 <- vn_openat
1 -> setf
1 -> fd_reserve
1 -> mutex_owned
1 <- mutex_owned
1 -> mutex_owned
1 <- mutex_owned
1 <- fd_reserve
1 -> cv_broadcast
1 <- cv_broadcast
1 <- setf
1 -> unfalloc
1 -> mutex_owned
1 <- mutex_owned
1 -> crfree
1 <- crfree
1 -> kmem_cache_free
1 -> kmem_cache_free_debug
1 -> kmem_log_enter
1 <- kmem_log_enter
1 -> tsc_gethrtime
1 <- tsc_gethrtime
推理示例
第13 章• 推理跟踪183
1 -> getpcstack
1 <- getpcstack
1 -> kmem_log_enter
1 <- kmem_log_enter
1 -> file_cache_destructor
1 -> mutex_destroy
1 <- mutex_destroy
1 <- file_cache_destructor
1 -> copy_pattern
1 <- copy_pattern
1 <- kmem_cache_free_debug
1 <- kmem_cache_free
1 <- unfalloc
1 -> set_errno
1 <- set_errno
1 <- copen
1 <- open
1 <= open 2
推理选项和调整
如果在尝试推理跟踪操作时推理缓冲区已满,则不会在缓冲区中存储任何数据,并将递增
删除计数。在此情况下,将会生成与以下示例类似的dtrace 消息:
dtrace: 38 speculative drops
在提交缓冲区后,推理删除不会阻止将整个推理缓冲区复制到主体缓冲区。类似地,即使
在最终放弃的推理缓冲区中执行过删除,也可能会发生推理删除。通过增加推理缓冲区大
小(使用specsize 选项调整),可减少推理删除。可以使用任何大小后缀指定specsize 选
项。调整此缓冲区大小的策略由bufresize 选项指示。
推理选项和调整
184 Solaris 动态跟踪指南• 2006 年7 月
调用speculation() 时,推理缓冲区可能不可用。如果存在尚未提交或放弃的缓冲区,则
会生成与以下示例类似的dtrace 消息:
dtrace: 1 failed speculation (no speculative buffer available)
通过使用nspec 选项增加推理缓冲区的数量,可以降低此特性的推理失败的可能性。nspec
的缺省值为1。
此外,speculation() 可能会因为所有推理缓冲区正忙而失败。在此情况下,将会生成与以
下示例类似的dtrace 消息:
dtrace: 1 failed speculation (available buffer(s) still busy)
此消息说明,在对推理缓冲区调用commit() 之后,但在所有CPU 中实际提交该缓冲区之
前,调用了speculation()。通过使用cleanrate 选项增加清除CPU 的速率,可以降低此特
性的推理操作失败的可能性。cleanrate 的缺省值为101。
推理选项和调整
第13 章• 推理跟踪185
186
dtrace(1M) 实用程序
dtrace(1M) 命令是DTrace 工具的通用前端。该命令实现了用于调用D语言编译器的简单界
面、通过DTrace 内核工具检索缓存的跟踪数据的功能以及一组用于格式化和列显跟踪数据
的基本例程。本章提供dtrace 命令的完整参考。
说明
dtrace 命令提供了一个可访问DTrace 工具提供的所有基本服务的通用界面,包括:
用于列出DTrace 当前发布的探测器和提供器集的选项
允许使用任何探测器说明符(提供器、模块、函数和名称)直接启用探测器的选项
用于运行D编辑器并编译一个或多个直接在命令行上编写的D程序文件或程序的选项
用于生成匿名跟踪程序的选项(请参见第36 章)
用于生成程序稳定性报告的选项(请参见第39 章)
用于修改DTrace 跟踪和缓冲行为并启用其他D编译器功能的选项(请参见第16 章)
还可通过在#! 声明中使用dtrace创建解释程序文件,来创建D脚本(请参见第15 章)。
最后,可在不使用-e 选项启用任何跟踪的情况下,使用dtrace 尝试编译D程序并确定它们
的属性,如下文所述。
选项
dtrace 命令接受下列选项:
dtrace [-32 | -64] [-aACeFGHlqSvVwZ] [-b bufsz] [-c cmd] [-D name [=def]] [-I path]
[-L path] [-o output] [-p pid] [-s script] [-U name] [-x arg [=val]] [-Xa | c | s | t]
[-P provider [ [predicate]action]] [-m [ [provider:]module [ [predicate]action]]]
[-f [ [provider:]module:]func [ [predicate]action]] [-n [ [ [provider:]module:]func:]name
[ [predicate]action]] [-i probe-id [ [predicate]action]]
14 第1 4 章
187
其中,predicate 是置于斜杠/ / 中的任何D 谓词,而action 是用括号{ } 括起来的任何D 语
句列表(根据先前说明的D语言语法)。如果将D程序代码提供为-P、-m, -f、-n 或-i 选
项的参数,则必须相应地用引号将此文本引起来以避免shell 对其进行解释。这些选项如下
所示:
-32, -64 D编译器使用操作系统内核的本机数据模型生成程序。可使用isainfo(1) -b 命
令确定当前操作系统的数据模型。如果指定了-32 选项,则dtrace 将强制D编
译器使用32 位数据模型编译D程序。如果指定了-64 选项,则dtrace 将强制D
编译器使用64 位数据模型编译D程序。通常这些选项不是必需的,因为dtrace
会选择本机数据模型作为缺省数据模型。数据模型会影响整数类型的大小和其
他语言属性。对任一数据模型编译的D程序可在32 位和64 位内核上执行。-32
和-64 选项还可确定-G 选项生成的ELF 文件格式(ELF32 或ELF64)。
-a 声明匿名跟踪状态并显示跟踪数据。可将-a 选项与-e 选项组合在一起,以强制
dtrace 在使用匿名跟踪状态后立即退出,而不是继续等待新数据。有关匿名跟
踪的更多信息,请参见第36 章。
-A 生成driver.conf(4) 指令以便进行匿名跟踪。如果指定了-A 选项,则dtrace 将
编译使用-s 选项或在命令行上指定的任何D程序,并构造dtrace(7D) 配置文件
指令集,以允许指定探测器进行匿名跟踪(请参见第36 章),然后退出。缺省
情况下,dtrace 尝试将指令存储到文件/kernel/drv/dtrace.conf 中。可通过使
用-o 选项指定备用输出文件来修改此行为。
-b 设置主体跟踪缓冲区大小。跟踪缓冲区大小可以使用任何大小后缀(k、m、g 或
t),如第36 章中所述。如果不能分配缓冲区空间,则dtrace 将根据bufresize
属性的设置减小缓冲区大小或退出。
-c 运行指定的命令cmd,并在完成时退出。如果命令行上有多个-c 选项,则
dtrace 将在所有命令退出后退出,并报告每个子进程终止时的退出状态。第一
个命令的进程ID 可供在命令行上(或者使用-s 选项通过$target 宏变量)指定
的任何D程序使用。有关宏变量的更多信息,请参阅第15 章。
-C 在编译D程序之前对它们运行C 预处理程序cpp(1)。可使用-D、-U、-I 和-H 选
项将这些选项传递到C 预处理程序。可使用-X 选项选择符合C 标准的程度。有
关在调用C 预处理程序时由D编译器定义的标记集的说明,请参阅-X 选项的说
明。
-D 在调用cpp(1)(使用-C 选项启用)时定义指定的name。如果指定了等号(=) 以
及value,则会将该值赋给名称。此选项将-D 选项传递到每个cpp 调用。
-e 在编译所有请求并使用匿名跟踪状态(-a 选项)之后、启用任何探测器之前退
出。此选项可与-a 选项组合在一起,用于列显匿名跟踪数据并退出,它也可以
与D编译器选项一起使用,用于验证在不实际执行程序并启用相应检测过程的
情况下,程序是否会进行编译。
-f 指定要跟踪或列出的函数名称(-l 选项)。相应参数可以包括下列任何探测器
说明形式:provider:module:function、module:function 或function。未指定的探测
器说明字段将留为空白,可与任何探测器相匹配,无论这些字段中的值是什
选项
188 Solaris 动态跟踪指南• 2006 年7 月
么。如果说明中仅指定了function 限定符,则会匹配所有包含相应function 的探
测器。可将可选D探测器子句用作-f 参数的后缀。在命令行上,一次可以指定
多个-f 选项。
-F 通过标识函数的入口和返回位置来合并跟踪输出。对函数入口的探测报告将进
行缩进,并在其输出内容前附带-> 前缀。对函数返回的探测报告将不进行缩
进,并在其输出内容前附带<- 前缀。
-G 生成包含嵌入式DTrace 程序的ELF 文件。在程序中指定的DTrace 探测器将保存
在可与其他程序链接的可重定位ELF 对象中。如果-o 选项存在,则会使用指定
为此操作数参数的路径名来保存ELF 文件。如果-o 选项不存在,并且DTrace 程
序与名为filename.s 的文件一起包含在ELF 文件中,则将使用名称file.o 来保存
ELF 文件;否则将使用名称d.out 来保存ELF 文件。
-H 在调用cpp(1)(使用-C 选项启用)时列显所包含文件的路径名。此选项会将-H
选项传递到每个cpp 调用,从而使调用将路径名的列表显示到stderr,每个路
径名显示为一行。
-i 指定要跟踪或列出的探测器标识符(-l 选项)。如dtrace -l 所示,探测器ID
指定为十进制整数。可将可选D探测器子句用作-i 参数的后缀。在命令行上,
一次可以指定多个-i 选项。
-I 在调用cpp(1)(使用-C 选项启用)时,将指定的目录path 添加到#include 文件
的搜索路径。此选项将-I 选项传递到每个cpp 调用。指定的目录将插入到缺省
目录列表之前的搜索路径中。
-l 列出探测器而不是启用它们。如果指定了-l 选项,则dtrace 将生成与使用
-P、-m、-f、-n、-i 和-s 选项指定的说明相匹配的探测器报告。如果未指定其
中任何选项,则将列出所有探测器。
-L 将指定的目录path 添加到DTrace 库的搜索路径。DTrace 库用于包含可在编写D
程序时使用的常见定义。指定的path 将添加到缺省库搜索路径后面。
-m 指定要跟踪或列出的模块名称(-l 选项)。相应参数可以包括下列任何探测器
说明形式:provider:module 或module。未指定的探测器说明字段将留为空白,并
且与任何探测器相匹配,无论这些字段中的值是什么。如果说明中仅指定了
module 限定符,则会匹配所有包含相应module 的探测器。可将可选D探测器子
句用作-m 参数的后缀。在命令行上,一次可以指定多个-m 选项。
-n 指定要跟踪或列出的探测器名称(-l 选项)。相应参数可以包括下列任何探测
器说明形式:provider:module:function:name、module:function:name、
function:name 或name。未指定的探测器说明字段将留为空白,并且与任何探测
器相匹配,无论这些字段中的值是什么。如果说明中仅指定了name 限定符,则
会匹配所有包含相应name 的探测器。可将可选D探测器子句用作-n 参数的后
缀。在命令行上,一次可以指定多个-n 选项。
-o 对-A、-G 和-l 选项或跟踪数据指定output 选项。如果-A 选项存在而-o 不存
在,则缺省输出文件为/kernel/drv/dtrace.conf 。如果-G 选项存在并且-s 选
项的参数为filename.d 形式,而-o 不存在,则缺省输出文件为filename.o;否则
缺省输出文件为d.out。
选项
阅读(438) | 评论(0) | 转发(0) |