DTrace ユーザーガイド

第 2 章 DTrace の基本

この章では、いくつかの基本タスクの例を示しながら、DTrace の機能全般を紹介します。

プローブの一覧を表示する

dtrace コマンドに -l オプションを指定すると、DTrace の全プローブの一覧を表示できます。


# dtrace -l
ID   PROVIDER    MODULE        FUNCTION NAME
 1     dtrace                           BEGIN
 2     dtrace                           END
 3     dtrace                           ERROR
 4    syscall                     nosys entry
 5    syscall                     nosys return
 6    syscall                     rexit entry
 7    syscall                     rexit return
 8    syscall                   forkall entry
 9    syscall                   forkall return
10    syscall                      read entry
11    syscall                      read return
...

システム上で使用可能な全プローブの数を確認するには、次のコマンドを入力します。


# dtrace -l | wc -l

報告されるプローブ数は、使用するオペレーティングプラットフォームとインストールされているソフトウェアの種類によって異なります。先ほどの例の BEGIN プローブと END プローブのように、MODULE 欄と FUNCTION 欄に何も表示されないことがあります。これらのフィールドが空になっているプローブは、特定の計測機能付きプログラムの関数や場所に対応していません。このようなプローブは、トレース要求の終わりなど、より抽象的な概念を表しています。プローブ名にモジュールや関数が含まれている場合、このプローブを「アンカーされたプローブ」と呼びます。特定のモジュールや関数に関連付けられていないプローブを「アンカーされていないプローブ」と呼びます。

次の例のように、オプションを追加して、特定のプローブだけを一覧表示できます。


例 2–1 関数を指定してプローブを一覧表示する

特定の関数に関連するプローブだけを一覧するには、-f オプションとその関数名を DTrace に指定します。


# dtrace -l -f cv_wait
ID      PROVIDER        MODULE        FUNCTION NAME
12921        fbt       genunix         cv_wait entry
12922        fbt       genunix         cv_wait return


例 2–2 モジュールを指定してプローブを一覧表示する

特定のモジュールに関連するプローブだけを一覧するには、-m オプションとそのモジュール名を DTrace に指定します。


# dtrace -l -m sd
ID      PROVIDER        MODULE        FUNCTION NAME
17147        fbt            sd          sdopen entry
17148        fbt            sd          sdopen return
17149        fbt            sd         sdclose entry
17150        fbt            sd         sdclose return
17151        fbt            sd      sdstrategy entry
17152        fbt            sd      sdstrategy return
...


例 2–3 名前を指定してプローブを一覧表示する

指定の名前のプローブを一覧するには、-n オプションとプローブ名を DTrace に指定します。


# dtrace -l -n BEGIN
ID      PROVIDER        MODULE        FUNCTION NAME
1         dtrace                               BEGIN


例 2–4 提供元のプロバイダを指定してプローブを一覧表示する

特定のプロバイダから提供されるプローブだけを一覧するには、-P オプションとそのプロバイダ名を DTrace に指定します。


# dtrace -l -P lockstat
ID        PROVIDER        MODULE             FUNCTION NAME
469       lockstat       genunix          mutex_enter adaptive-acquire
470       lockstat       genunix          mutex_enter adaptive-block
471       lockstat       genunix          mutex_enter adaptive-spin
472       lockstat       genunix           mutex_exit adaptive-release
473       lockstat       genunix        mutex_destroy adaptive-release
474       lockstat       genunix       mutex_tryenter adaptive-acquire
...


例 2–5 複数のプロバイダでサポートされる関数とモジュール

一部の関数またはモジュールは、次の例のように、複数のプロバイダでサポートされることがあります。


# dtrace -l -f read
ID        PROVIDER        MODULE             FUNCTION NAME
  10       syscall                               read entry
  11       syscall                               read return
4036       sysinfo       genunix                 read readch
4040       sysinfo       genunix                 read sysread
7885           fbt       genunix                 read entry
7886           fbt       genunix                 read return

これまでの例が示すように、プローブ一覧の出力内容は次のとおりです。

DTrace でプローブを指定する

プローブを一意に識別する 4 つの要素を指定することにより、プローブを完全指定できます。プローブは次の形式で指定します。provider:module:function:name。プローブの要素の指定を省略すると、任意の要素を指定したことになります。たとえば、fbt::alloc:entry は、次の属性のプローブを指定しています。

4 つの要素のうち、前半は省略可能です。::open:entry と指定した場合、open:entry と指定したのと同じことになります。どちらも、すべてのプロバイダおよびカーネルモジュールからの、関数名が open、プローブ名が entry であるプローブを指定したことになります。


# dtrace -l -n open:entry
  ID      PROVIDER        MODULE             FUNCTION NAME
  14       syscall                               open entry
7386           fbt       genunix                 open entry

sh(1) のマニュアルページの「ファイル名の生成」のセクションに記載されている構文と同様のパターンマッチング構文を使って、プローブを指定することもできます。この構文では、特殊文字 *?[、および ] を使用できます。プローブ記述 syscall::open*:entry は、openopen64 の両方のシステムコールを意味します。? は、名前に含まれる任意の 1 文字を表します。[] 文字は、名前に含まれる特定の文字列を指定するために使用します。

プローブを有効にする

プローブを有効にするには、-l オプションを付けずにプローブを指定して、dtrace コマンドを実行します。指定のプローブが起動すると、DTrace はデフォルトのアクションを実行します。特別な指示は不要です。デフォルトのプローブアクションでは、指定のプローブが起動したことだけが示されます。それ以外のデータは記録されません。次に示すのは、sd モジュールに含まれるすべてのプローブを有効にするコード例です。


例 2–6 モジュールを指定してプローブを有効にする


# dtrace -m sd
CPU     ID                     FUNCTION:NAME
  0  17329           sd_media_watch_cb:entry
  0  17330          sd_media_watch_cb:return
  0  17167                      sdinfo:entry
  0  17168                     sdinfo:return
  0  17151                  sdstrategy:entry
  0  17152                 sdstrategy:return
  0  17661          ddi_xbuf_qstrategy:entry
  0  17662         ddi_xbuf_qstrategy:return
  0  17649                xbuf_iostart:entry
  0  17341            sd_xbuf_strategy:entry
  0  17385                sd_xbuf_init:entry
  0  17386               sd_xbuf_init:return
  0  17342           sd_xbuf_strategy:return
  0  17177     sd_mapblockaddr_iostart:entry
  0  17178    sd_mapblockaddr_iostart:return
  0  17179               sd_pm_iostart:entry
  0  17365                 sd_pm_entry:entry
  0  17366                sd_pm_entry:return
  0  17180              sd_pm_iostart:return
  0  17181             sd_core_iostart:entry
  0  17407         sd_add_buf_to_waitq:entry
...

この例の出力では、デフォルトアクションによって、プローブが起動した CPU、DTrace によって割り当てられたプローブ ID (整数値)、プローブが起動した関数、およびプローブ名が表示されています。



例 2–7 プロバイダを指定してプローブを有効にする


# dtrace -P syscall
dtrace: description 'syscall' matched 452 probes
CPU     ID                     FUNCTION:NAME
  0     99                      ioctl:return
  0     98                       ioctl:entry
  0     99                      ioctl:return
  0     98                       ioctl:entry
  0     99                      ioctl:return
  0    234                   sysconfig:entry
  0    235                  sysconfig:return
  0    234                   sysconfig:entry
  0    235                  sysconfig:return
  0    168                   sigaction:entry
  0    169                  sigaction:return
  0    168                   sigaction:entry
  0    169                  sigaction:return
  0     98                       ioctl:entry
  0     99                      ioctl:return
  0    234                   sysconfig:entry
  0    235                  sysconfig:return
  0     38                         brk:entry
  0     39                        brk:return
...


例 2–8 名前を指定してプローブを有効にする


# dtrace -n zfod
dtrace: description 'zfod' matched 3 probes
CPU     ID                     FUNCTION:NAME
  0   4080                    anon_zero:zfod
  0   4080                    anon_zero:zfod
^C


例 2–9 名前を完全指定してプローブを有効にする


# dtrace -n clock:entry
dtrace: description 'clock:entry' matched 1 probe
CPU     ID                     FUNCTION:NAME
  0   4198                       clock:entry
^C

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 スクリプト言語のすべての組み込み変数については、「DTrace の組み込み変数」を参照してください。

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) です。したがって、一番右の欄にプロセス ID 番号 (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 システムコールの開始時刻をトレースする


# 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)

もっとも基本的なアクションは、D 式 expression を引数とし、指定バッファーに結果をトレースする trace() アクションです。

tracemem() 関数

void tracemem(address, size_t nbytes)

tracemem() アクションは、メモリー内のアドレスからバッファーにデータをコピーします。nbytes には、このアクションによってコピーされるバイト数を指定します。address には、コピーされるデータのアドレスを D 式で指定します。指定バッファーにコピーします。

printf() 関数

void printf(string format, ...) 

printf() アクションは、trace() アクションと同じように 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() アクションを処理したときに、シンボルに翻訳されます。strsize にゼロ以外の値を指定した場合、ustack() アクションは指定された容量の文字列空間を割り当て、これを使ってカーネルから直接、アドレスからシンボルへの翻訳を行います。

jstack() 関数

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

jstack() アクションは、ustack() アクションの別名で、スタックフレーム数については jstackframes オプションに指定されている値を使用します。jstackアクションは、jstackstrsize オプションに指定された値を使って、文字列空間のサイズを決定します。デフォルトでは、jstacksize アクションはゼロ以外の値になります。

破壊アクション

破壊アクションを使用するためには、明示的な方法で有効にする必要があります。-w オプションを使用すれば、破壊アクションを有効にできます。破壊アクションを明示的に有効にしないまま、dtrace 内でその使用を試みると、dtrace は失敗し、次のようなメッセージが表示されます。

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

破壊アクションをはじめとする DTrace アクションについては、『Solaris 動的トレースガイド』の第 10 章「アクションとサブルーチン」を参照してください。

プロセス破壊アクション

一部の破壊アクションは、特定のプロセスだけに影響を及ぼします。こうしたアクションを実行できるのは、dtrace_proc 権限か dtrace_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 で指定されたプログラムを、シェルに入力として渡されたときのようにして実行します。

カーネル破壊アクション

システム全体に影響を及ぼす破壊アクションもあります。これらのアクションは慎重に使用してください。これらのアクションは、システムで実行中のすべてのプロセスに影響を及ぼします。さらに、そのシステムのネットワークサービスを使用しているその他のシステムに影響を及ぼすこともあります。

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() を使用すると、割り込み遅延、スケジュール遅延、ディスパッチ遅延が発生します。

DTrace 集積体

パフォーマンス関連の問題を調査するときは、通常、個々のデータポイントではなく、集積データを調べるほうが効果的です。DTrace には、いくつかの組み込みの集積関数が用意されています。データ集合のサブセットに集積関数を適用し、これらのサブセットの分析結果に再度集積関数を適用すると、データ集合全体に集積関数を適用した場合と同じ結果になります。

DTrace 機能は、集積のため、データ項目のランニングカウントを格納します。集積関数は、現在の中間結果と、関数の適用先の新規要素のみを格納します。中間結果は、CPU 単位で割り当てられます。この割り当て方式では、ロックは必要ありません。したがって、実装は本質的にスケーラブルです。

DTrace 集積体の構文

DTrace 集積体の一般構文は、次のとおりです。

@name[ keys ] = aggfunc( args );

この一般構文では、変数は次のように定義されています。

name

集積体の名前。先頭に @ 文字が付きます。

keys

D 式をコンマで区切って指定します。

aggfunc

DTrace 集積関数のいずれか。

args

その集積関数に対応する引数をコンマで区切って指定します。

表 2–1 DTrace の集積関数

関数名 

引数 

結果 

count

なし 

count 関数が呼び出される回数。

sum

スカラー式 

指定された式の合計値。 

avg

スカラー式 

指定された式の算術平均。 

min

スカラー式 

指定された式のうちもっとも小さい値。 

max

スカラー式 

指定された式のうちもっとも大きい値。 

lquantize

スカラー式、下限値、上限値、ステップ値 

指定された式の値から成る、指定された範囲の線形度数分布。この集積関数は、指定された式より小さい、最大バケット内の値を増分します。

quantize

スカラー式 

指定された式の値の二乗度数分布。この集積関数は、指定された式より小さい、2 のべき乗の最大バケット内の値を増分します。


例 2–14 集積関数の使用法

次に示すのは、count 集積関数を使って、プロセスごとに write(2) システムコールの数をカウントする例です。この集積体は、dtrace コマンドが終了するまで、一切のデータを出力しません。出力される内容は、dtrace コマンドがアクティブであったときに収集されたデータの概要です。


# cat writes.d
#!/usr/sbin/dtrace -s
syscall::write:entry]
{   @numWrites[execname] = count();
}

# ./writes.d
dtrace: script 'writes.d' matched 1 probe
^C
  dtrace                           1
  date                             1
  bash                             3
  grep                            20
  file                           197
  ls                             201