JavaScript is required to for searching.
跳过导航链接
退出打印视图
DTrace 用户指南     Oracle Solaris 10 8/11 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  简介

2.  DTrace 基础知识

列出探测器

在 DTrace 中指定探测器

启用探测器

DTrace 操作基础知识

数据记录操作

trace() 函数

tracemem() 函数

printf() 函数

printa() 函数

stack() 函数

ustack() 函数

jstack() 函数

破坏性操作

处理破坏性操作

stop() 函数

raise() 函数

copyout() 函数

copyoutstr() 函数

system() 函数

内核破坏性操作

breakpoint() 函数

panic() 函数

chill() 函数

DTrace 聚合

DTrace 聚合语法

3.  使用 D 语言编写脚本

4.  使用 DTrace

索引

DTrace 操作基础知识

操作使得 DTrace 能够与 DTrace 框架外的系统进行交互。大多数常见操作将数据记录到 DTrace 缓冲区。其他操作可能会停止当前进程,在当前进程上发出特定信号,或者停止跟踪。更改系统状态的操作被视为破坏性操作。缺省情况下,数据记录操作将数据记录到主体缓冲区。主体缓冲区是在每个 DTrace 调用中提供的,并且始终是为每个 CPU 分别分配的。可以通过使用 -cpu 选项将跟踪和缓冲区分配限定到单个 CPU。有关 DTrace 缓冲的更多信息,请参见《Solaris 动态跟踪指南》中的第 11  章 "缓冲区和缓冲"

本节中的示例使用了由内置的 D 变量组成的 D 表达式。下面列出了一些最常用的 D 变量:

pid

此变量包含当前进程 ID。

execname

此变量包含当前的可执行文件名称。

timestamp

此变量包含自引导以来经过的时间,以纳秒为单位。

curthread

此变量包含指向表示当前线程的 kthread_t 结构的一个指针。

probemod

此变量包含当前探测器的模块名称。

probefunc

此变量包含当前探测器的函数名称。

probename

此变量包含当前探测器的名称。

有关 D 脚本语言的内置变量的完整列表,请参见变量。

D 脚本语言还提供了执行特定操作的内置函数。可以在《Solaris 动态跟踪指南》中的第 10  章 "操作和子例程"trace() 函数将 D 表达式的结果记录到跟踪缓冲区,如下列示例所述:

要指定您想要探测器采取的特定操作,请在 {} 字符中间键入操作的名称,如下例所示。

示例 2-10 指定探测器的操作

# dtrace -n 'readch {trace(pid)}'
dtrace: description 'readch ' matched 4 probes
CPU     ID                     FUNCTION:NAME
  0   4036                       read:readch          2040
  0   4036                       read:readch          2177
  0   4036                       read:readch          2177
  0   4036                       read:readch          2040
  0   4036                       read:readch          2181
  0   4036                       read:readch          2181
  0   4036                       read:readch             7
...

因为所请求的操作是 trace(pid),所以进程标识号 (PID) 显示在输出的最后一列中。

示例 2-11 跟踪可执行文件名称

# dtrace -m 'ufs {trace(execname)}'
dtrace: description 'ufs ' matched 889 probes
CPU     ID                     FUNCTION:NAME
  0  14977                  ufs_lookup:entry            ls
  0  15748                 ufs_iaccess:entry            ls
  0  15749                ufs_iaccess:return            ls
  0  14978                 ufs_lookup:return            ls
...
  0  15007                    ufs_seek:entry         utmpd
  0  15008                   ufs_seek:return         utmpd
  0  14963                   ufs_close:entry         utmpd
^C

示例 2-12 跟踪 Entry 的系统调用时间

# dtrace -n 'syscall:::entry {trace(timestamp)}'
dtrace: description 'syscall:::entry ' matched 226 probes
CPU     ID                     FUNCTION:NAME
  0    312                      portfs:entry    157088479572713
  0     98                       ioctl:entry    157088479637542
  0     98                       ioctl:entry    157088479674339
  0    234                   sysconfig:entry    157088479767243
...
  0     98                       ioctl:entry    157088481033225
  0     60                       fstat:entry    157088481050686
  0     60                       fstat:entry    157088481074680
^C

示例 2-13 指定多个操作

要指定多个操作,请列出以 ; 字符分隔的各个操作。

# dtrace -n 'zfod {trace(pid);trace(execname)}'
dtrace: description 'zfod ' matched 3 probes
CPU     ID                     FUNCTION:NAME
  0   4080                    anon_zero:zfod    2195   dtrace
  0   4080                    anon_zero:zfod    2195   dtrace
  0   4080                    anon_zero:zfod    2195   dtrace
  0   4080                    anon_zero:zfod    2195   dtrace
  0   4080                    anon_zero:zfod    2195   dtrace
  0   4080                    anon_zero:zfod    2197   bash
  0   4080                    anon_zero:zfod    2207   vi
  0   4080                    anon_zero:zfod    2207   vi
...

数据记录操作

缺省情况下,本节中的操作将数据记录到主体缓冲区,但还可以使用各个操作将数据记录到推理缓冲区。有关推理缓冲区的更多详细信息,请参见推理跟踪

trace() 函数

void trace(expression)

最基本的操作是 trace() 操作,此操作将 D 表达式用作其参数并跟踪结果到定向缓冲区。

tracemem() 函数

void tracemem(address, size_t nbytes)

tracemem() 操作将数据从内存中的某个地址复制到缓冲区中。此操作复制的字节数是在 nbytes 中指定的。从中复制数据的地址是在 addr 中以 D 表达式的形式指定的。将数据复制到的缓冲区是在 buf 中指定的。

printf() 函数

void printf(string format, ...) 

trace() 操作一样,printf() 操作跟踪 D 表达式。不过,printf() 操作允许您控制格式,这类似于 printf(3C) 函数。与 printf 函数一样,参数包括一个 format 字符串,后跟任意数量的参数。缺省情况下,将跟踪参数到定向缓冲区。然后,dtrace 命令将根据指定的格式字符串对参数进行格式化,以便输出。

有关 printf() 操作的更多信息,请参见《Solaris 动态跟踪指南》中的第 12  章 "输出格式化"

printa() 函数

void printa(aggregation)
void printa(string format, aggregation)

使用 printa() 操作可以显示和格式化聚合。有关聚合的更多详细信息,请参见《Solaris 动态跟踪指南》中的第 9  章 "聚合"。如果没有提供 format 值,则 printa() 操作仅向 DTrace 使用者发送一条指令。接收该指令的使用者将处理聚合并以缺省格式显示聚合。有关 printa() 格式字符串的更详细描述,请参见《Solaris 动态跟踪指南》中的第 12  章 "输出格式化"

stack() 函数

void stack(int nframes)
void stack(void)

stack() 操作会将内核栈跟踪记录到定向缓冲区。内核栈的深度是由 nframes 中指定的值指定的。如果没有为 nframes 指定值,则 stack 操作将记录由 stackframes 选项指定的数目的栈帧。

ustack() 函数

void ustack(int nframes, int strsize)
void ustack(int nframes)
void ustack(void)

ustack() 操作将用户栈跟踪记录到定向缓冲区中。用户栈的深度等于 nframes 中指定的值。如果没有指定 nframes 的值,则 ustack 操作将记录由 ustackframes 选项指定的数目的栈帧。ustack() 操作在探测器触发时确定调用帧的地址。在 DTrace 使用者在用户级别处理 ustack() 操作之前,ustack() 操作不会将栈帧转换为符号。如果为 strsize 指定了一个非零值,则 ustack() 操作会分配指定数量的字符串空间并使用它直接从内核执行“地址到符号”转换。

jstack() 函数

void jstack(int nframes, int strsize)
void jstack(int nframes)
void jstack(void)

jstack() 操作是使用由 jstackframes 选项指定的栈帧数目的 ustack() 的别名。jstack 操作使用由 jstackstrsize 选项指定的值来确定字符串空间大小。jstacksize 操作缺省使用某个非零值。

破坏性操作

要使用破坏性操作,您必须显式启用它们。可以使用 -w 选项启用破坏性操作。如果您在没有显式启用破坏性操作的情况下试图在 dtrace 中使用它们,则 dtrace 将失败,且返回类似于下例的一条消息:

dtrace: failed to enable 'syscall': destructive actions not allowed

有关 DTrace 操作的更多信息(包括破坏性操作),请参见《Solaris 动态跟踪指南》中的第 10  章 "操作和子例程"

处理破坏性操作

某些操作仅对特定进程具有破坏性。具有 dtrace_procdtrace_user 权限的用户可以使用这些操作。有关 DTrace 安全权限的详细信息,请参见《Solaris 动态跟踪指南》中的第 35  章 "安全性"

stop() 函数

如果探测器是在启用了 stop() 操作的情况下触发的,则触发该探测器的进程将在离开内核时停止。该进程的停止方式与由proc(4) 操作停止的进程的停止方式相同。

raise() 函数
void raise(int signal)

raise() 操作将指定的信号发送至当前正在运行的进程。

copyout() 函数
void copyout(void *buf, uintptr_t addr, size_t nbytes)

copyout() 操作将数据从缓冲区复制到内存中的地址。此操作复制的字节数是在 nbytes 中指定的。从其中复制数据的缓冲区是在 buf 中指定的。将数据复制到的地址是在 addr 中指定的。该地址位于与当前线程相关联进程的地址空间中。

copyoutstr() 函数
void copyoutstr(string str, uintptr_t addr, size_t maxlen)

copyoutstr() 操作将字符串复制到内存中的地址。要复制的字符串是在 str 中指定的。将字符串复制到的地址是在 addr 中指定的。该地址位于与当前线程相关联进程的地址空间中。

system() 函数
void system(string program, ...) 

system() 操作导致系统执行由 program 指定的程序,就像该程序被作为输入传递给 shell 一样。

内核破坏性操作

一些破坏性操作对整个系统都具有破坏性。请慎用这些操作。这些操作影响系统上的每个进程,并且可能会影响其他系统,具体取决于受影响系统的网络服务。

breakpoint() 函数
void breakpoint(void)

breakpoint() 操作会引起内核断点,从而使系统停止并将控制转移到内核调试器。内核调试器将发出一个字符串,表示触发该操作的 DTrace 探测器。

panic() 函数
void panic(void)

当包含 panic() 操作的探测器触发时,内核将崩溃。该操作可以在某个重要时间强制执行系统故障转储。您可以将该操作与环形缓冲和事后分析结合使用来对系统问题进行诊断。有关更多信息,请分别参见《Solaris 动态跟踪指南》中的第 11  章 "缓冲区和缓冲"《Solaris 动态跟踪指南》中的第 37  章 "事后跟踪"

chill() 函数
void chill(int nanoseconds)

当包含 chill() 操作的探测器触发时,DTrace 将旋转指定的纳秒数。chill() 操作对于探究与计时有关的问题非常有用。由于处于 DTrace 探测器上下文中时禁止中断,因此使用任何 chill() 都将引起中断延迟、调度延迟和分发延迟。