この章では、D 言語を使って独自のスクリプトを作成するときに必要となる基本情報を提供します。
DTrace プローブを複雑に組み合わせると、コマンド行での使用が難しくなる場合もあります。dtrace コマンドは、スクリプトをサポートしています。dtrace コマンドに -s オプションとスクリプトファイル名を指定することで、スクリプトを指定できます。実行可能な DTrace インタプリタファイルも作成できます。DTrace インタプリタファイルは、常に #!/usr/sbin/dtrace -s から始まります。
次のサンプルスクリプト syscall.d は、実行可能ファイルがシステムコールを開始するたびに、その実行可能ファイルの名前をトレースします。
syscall:::entry { trace(execname); }
ファイル名は接尾辞 .d で終わっています。D スクリプトの末尾は、通常、この形式になります。このスクリプトは、DTrace コマンド行から次のコマンドを使用して実行できます。
# dtrace -s syscall.d dtrace: description 'syscall ' matched 226 probes CPU ID FUNCTION:NAME 0 312 pollsys:entry java 0 98 ioctl:entry dtrace 0 98 ioctl:entry dtrace 0 234 sysconfig:entry dtrace 0 234 sysconfig:entry dtrace 0 168 sigaction:entry dtrace 0 168 sigaction:entry dtrace 0 98 ioctl:entry dtrace ^C |
このスクリプトは、次の 2 つの手順でコマンド行にファイル名を指定する方法で実行できます。まず、ファイルの先頭行がインタプリタの呼び出しになっていることを確認します。インタプリタの呼び出し行は、#!/usr/sbin/dtrace -s です。次に、ファイルの実行権を設定します。
# cat syscall.d #!/usr/sbin/dtrace -s syscall:::entry { trace(execname); } # chmod +x syscall.d # ls -l syscall.d -rwxr-xr-x 1 root other 62 May 12 11:30 syscall.d # ./syscall.d dtrace: script './syscall.d' matched 226 probes CPU ID FUNCTION:NAME 0 98 ioctl:entry dtrace 0 98 ioctl:entry dtrace 0 312 pollsys:entry java 0 312 pollsys:entry java 0 312 pollsys:entry java 0 98 ioctl:entry dtrace 0 98 ioctl:entry dtrace 0 234 sysconfig:entry dtrace 0 234 sysconfig:entry dtrace ^C |
D 言語はリテラル文字列をサポートします。DTrace の文字列は、NULL バイトで終了する文字配列として表現されます。文字列の可視部分は可変長で、NULL バイトの位置によって長さが決まります。DTrace は、各プローブが決まった量のデータをトレースするように、各文字列を固定サイズの配列に格納します。文字列の長さは、あらかじめ定義された文字列制限長を超えることはできません。この制限は D プログラム内で変更できます。dtrace コマンド行で strsize オプションをチューニングして変更することもできます。チューニング可能な DTrace オプションについては、『Solaris 動的トレースガイド』の第 16 章「オプションとチューニング可能パラメータ」を参照してください。デフォルトの制限長は 256 バイトです。
D 言語で文字列を参照するときは、char * 型ではなく、明示的な string 型を使用します。D リテラル文字列については、『Solaris 動的トレースガイド』の第 6 章「文字列」を参照してください。
# cat string.d #!/usr/sbin/dtrace -s fbt::bdev_strategy:entry { trace(execname); trace(" is initiating a disk I/O\n"); } |
このリテラル文字列の末尾の記号 \n によって、新規の行が生成されます。このスクリプトを実行するには、次のコマンドを入力します。
# dtrace -s string.d dtrace: script 'string.d' matched 1 probes CPU ID FUNCTION:NAME 0 9215 bdev_strategy:entry bash is initiating a disk I/O 0 9215 bdev_strategy:entry vi is initiating a disk I/O 0 9215 bdev_strategy:entry vi is initiating a disk I/O 0 9215 bdev_strategy:entry sched is initiating a disk I/O ^C |
dtrace コマンドを -q オプション付きで実行した場合、スクリプト内またはコマンド行呼び出しに明示的に指定されたアクションだけが記録されます。dtrace コマンドが通常生成するデフォルト出力は抑制されます。
# dtrace -q -s string.d ls is initiating a disk I/O cat is initiating a disk I/O fsflush is initiating a disk I/O vi is initiating a disk I/O ^C |
dtrace コマンドを使って、実行可能なインタプリタファイルを作成できます。このファイルには、実行権を設定する必要があります。ファイルの先頭行は、#!/usr/sbin/dtrace -s にする必要があります。この行には、dtrace コマンドのほかのオプションを指定できます。複数のオプションを指定する場合も、ダッシュ (-) は 1 つだけ入力してください。s オプションは、次の例のように、最後に指定してください。
#!/usr/sbin/dtrace -qvs |
dtrace コマンドのオプションを、D スクリプトの #pragma 行を使用して指定できます。次の D スクリプトの抜粋を参照してください。
# cat -n mem2.d 1 #!/usr/sbin/dtrace -s 2 3 #pragma D option quiet 4 #pragma D option verbose 5 6 vminfo::: ... |
次の表に、#pragma 行で使用できるオプション名を一覧します。
表 3–1 DTrace コンシューマオプション
オプション名 |
値 |
dtrace 別名 |
説明 |
---|---|---|---|
aggrate |
時間 |
集積体の読み取りレート |
|
aggsize |
サイズ |
集積体バッファーサイズ |
|
bufresize |
auto または manual |
バッファーのサイズ変更ポリシー |
|
bufsize |
サイズ |
-b |
主バッファーサイズ |
cleanrate |
時間 |
クリーンアップレート |
|
cpu |
スカラー |
-c |
トレースを有効にする CPU |
defaultargs |
— |
未知のマクロ引数の参照を許可する |
|
destructive |
— |
-w |
破壊アクションを許可する |
dynvarsize |
サイズ |
動的変数空間のサイズ |
|
flowindent |
— |
-F |
関数の開始 (entry) をインデントし、その前に -> を付ける。関数の終了 (return) のインデントを解除し、その前に <- を付ける |
grabanon |
— |
-a |
匿名状態を要求する |
jstackframes |
スカラー |
jstack() のデフォルトスタックフレームの数 |
|
jstackstrsize |
スカラー |
jstack() の文字列空間のデフォルトサイズ |
|
nspec |
スカラー |
投機の数 |
|
quiet |
— |
-q |
明示的にトレースされたデータだけを出力する |
specsize |
サイズ |
投機バッファーサイズ |
|
strsize |
サイズ |
文字列サイズ |
|
stackframes |
スカラー |
スタックフレームの数 |
|
stackindent |
スカラー |
stack() と ustack() の出力をインデントするときに使用する空白文字の数 |
|
statusrate |
時間 |
状態チェックレート |
|
switchrate |
時間 |
バッファー切り替えレート |
|
ustackframes |
スカラー |
ユーザースタックフレームの数 |
一連の組み込みマクロ変数も、D スクリプトで参照できます。これらのマクロ変数は、D コンパイラで定義されます。
マクロ引数
実効グループ ID
実効ユーザー ID
実グループ ID
プロセス ID
プロセスグループ ID
親プロセス ID
プロジェクト ID
セッション ID
ターゲットプロセス ID
タスク ID
実ユーザー ID
次の例では、D スクリプト syscalls2.d に、実行中の vi プロセスの PID が渡されます。vi コマンドが終了すると、D スクリプトも終了します。
# cat -n syscalls2.d 1 #!/usr/sbin/dtrace -qs 2 3 syscall:::entry 4 /pid == $1/ 5 { 6 @[probefunc] = count(); 7 } 8 syscall::rexit:entry 9 { 10 exit(0); 11 } # pgrep vi 2208 # ./syscalls2.d 2208 rexit 1 setpgrp 1 creat 1 getpid 1 open 1 lstat64 1 stat64 1 fdsync 1 unlink 1 close 1 alarm 1 lseek 1 sigaction 1 ioctl 1 read 1 write 1 |
次に、DTrace フレームワークのすべての組み込み変数を一覧します。
プローブに渡される最初の 10 個の入力引数は、生の 64 ビット整数として表現されます。プローブに渡された引数の数が 10 個未満の場合、残りの変数はゼロを返します。
現在のプローブに渡される型付き引数です (存在する場合)。args[] 配列へのアクセスには整数インデックスが使用されますが、各要素には、指定のプローブ引数に対応する型が定義されます。たとえば、read(2) システムコールプローブで args[] を参照する場合、args[0] の型は int、args[1] の型は void *、args[2] の型は size_t になります。
現在のプローブを入力する直前の、現在のスレッドのプログラムカウンタの場所を示します。
現在の物理チップの CPU チップ識別子です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。
現在の CPU の CPU 識別子です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。
現在の CPU の CPU 情報です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。
現在のスレッドに関連付けられている軽量プロセス (LWP) の LWP 状態です。この構造の詳細は、proc(4) のマニュアルページに記載されています。
現在のスレッドに関連付けられているプロセスのプロセス状態です。この構造の詳細は、proc(4) のマニュアルページに記載されています。
現在のスレッドのオペレーティングシステムカーネルの内部データ構造 kthread_t のアドレスです。kthread_t は <sys/thread.h> に定義されています。この変数とその他のオペレーティングシステムデータ構造の詳細は、『SOLARIS インターナル — カーネル構造のすべて』を参照してください。
現在のスレッドに関連付けられているプロセスの現在の作業ディレクトリ名です。
現在のプローブの有効なプローブ ID (EPID) です。この整数は、特定の述語と一連のアクションによって有効化された特定のプローブを一意に識別します。
このスレッドによって直前に実行されたシステムコールから返されるエラー値です。
現在のプロセスを実行するため、exec(2) に渡された名前です。
現在のプロセスの実グループ ID です。
現在のプローブのプローブ ID です。この ID は、DTrace によって発行された、システム内のプローブを一意に識別する識別子です。この ID を確認するには、dtrace -l を実行します。
現在の CPU でのプローブ起動時の割り込み優先レベル (IPL) を表します。Solaris オペレーティングシステムカーネルでの割り込みレベルと割り込み処理の詳細は、『SOLARIS インターナル — カーネル構造のすべて』を参照してください。
現在の CPU をメンバーに持つ遅延グループの近傍性グループ ID です。DTrace での CPU 管理については、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。近傍性グループについては、『プログラミングインタフェース』の第 4 章「近傍性グループ API」を参照してください。
現在のプロセスのプロセス ID です。
現在のプロセスの親プロセスのプロセス ID です。
現在のプローブの記述に含まれる関数名の部分です。
現在のプローブの記述に含まれるモジュール名の部分です。
現在のプローブの記述に含まれる名前の部分です。
現在のプローブの記述に含まれるプロバイダ名の部分です。
現在の CPU が含まれているプロセッサセットのプロセッサセット ID です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。
現在のスレッドに関連付けられているプロセスのルートディレクトリ名です。
現在のスレッドのプローブ起動時のスタックフレームの深さを表します。
現在のスレッドのスレッド ID です。スレッドにユーザープロセスが関連付けられている場合、この値は、pthread_self(3C) の呼び出し結果と等しくなります。
ナノ秒タイムスタンプカウンタの現在の値です。このカウンタの値は、過去の任意の時点から増分しています。そのため、このカウンタは、相対計算専用です。
現在のプロセスの実ユーザー ID です。
現在のスレッドの、プローブ起動時のユーザーモード登録値 (保存済み) です。uregs[] 配列の使用方法については、『Solaris 動的トレースガイド』の第 33 章「ユーザープロセスのトレース」を参照してください。
ナノ秒タイムスタンプカウンタの現在の値です。このカウンタは、現在のスレッドの CPU 上での実行時間を示します。これには、DTrace の述語やアクションの実行にかかる時間は含まれません。このカウンタの値は、過去の任意の時点から増分しています。そのため、このカウンタは、相対時間計算専用です。
1970 年 1 月 1 日の協定世界時 00:00 から現在までの経過時間をナノ秒単位で示します。