DTrace ユーザーガイド

第 3 章 D 言語を使ったスクリプトの作成

この章では、D 言語を使って独自のスクリプトを作成するときに必要となる基本情報を提供します。

D スクリプトの作成

DTrace プローブを複雑に組み合わせると、コマンド行での使用が難しくなる場合もあります。dtrace コマンドは、スクリプトをサポートしています。dtrace コマンドに -s オプションとスクリプトファイル名を指定することで、スクリプトを指定できます。実行可能な DTrace インタプリタファイルも作成できます。DTrace インタプリタファイルは、常に #!/usr/sbin/dtrace -s から始まります。

実行可能な D スクリプト

次のサンプルスクリプト 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 です。次に、ファイルの実行権を設定します。


例 3–1 コマンド行から D スクリプトを実行する


# 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 リテラル文字列

D 言語はリテラル文字列をサポートします。DTrace の文字列は、NULL バイトで終了する文字配列として表現されます。文字列の可視部分は可変長で、NULL バイトの位置によって長さが決まります。DTrace は、各プローブが決まった量のデータをトレースするように、各文字列を固定サイズの配列に格納します。文字列の長さは、あらかじめ定義された文字列制限長を超えることはできません。この制限は D プログラム内で変更できます。dtrace コマンド行で strsize オプションをチューニングして変更することもできます。チューニング可能な DTrace オプションについては、『Solaris 動的トレースガイド』の第 16 章「オプションとチューニング可能パラメータ」を参照してください。デフォルトの制限長は 256 バイトです。

D 言語で文字列を参照するときは、char * 型ではなく、明示的な string 型を使用します。D リテラル文字列については、『Solaris 動的トレースガイド』の第 6 章「文字列」を参照してください。


例 3–2 trace() 関数で D リテラル文字列を使用する


# 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

引数を使用する D スクリプトを作成する

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 コンパイラで定義されます。

$[0-9]+

マクロ引数

$egid

実効グループ ID

$euid

実効ユーザー ID

$gid

実グループ ID

$pid

プロセス ID

$pgid

プロセスグループ ID

$ppid

親プロセス ID

$projid

プロジェクト ID

$sid

セッション ID

$target

ターゲットプロセス ID

$taskid

タスク ID

$uid

実ユーザー ID


例 3–3 PID 引数の例

次の例では、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 の組み込み変数

次に、DTrace フレームワークのすべての組み込み変数を一覧します。

int64_t arg0, ..., arg9

プローブに渡される最初の 10 個の入力引数は、生の 64 ビット整数として表現されます。プローブに渡された引数の数が 10 個未満の場合、残りの変数はゼロを返します。

args[]

現在のプローブに渡される型付き引数です (存在する場合)。args[] 配列へのアクセスには整数インデックスが使用されますが、各要素には、指定のプローブ引数に対応する型が定義されます。たとえば、read(2) システムコールプローブで args[] を参照する場合、args[0] の型は intargs[1] の型は void *args[2] の型は size_t になります。

uintptr_t caller

現在のプローブを入力する直前の、現在のスレッドのプログラムカウンタの場所を示します。

chipid_t chip

現在の物理チップの CPU チップ識別子です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。

processorid_t cpu

現在の CPU の CPU 識別子です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。

cpuinfo_t *curcpu

現在の CPU の CPU 情報です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。

lwpsinfo_t *curlwpsinfo

現在のスレッドに関連付けられている軽量プロセス (LWP) の LWP 状態です。この構造の詳細は、proc(4) のマニュアルページに記載されています。

psinfo_t *curpsinfo

現在のスレッドに関連付けられているプロセスのプロセス状態です。この構造の詳細は、proc(4) のマニュアルページに記載されています。

kthread_t *curthread

現在のスレッドのオペレーティングシステムカーネルの内部データ構造 kthread_t のアドレスです。kthread_t<sys/thread.h> に定義されています。この変数とその他のオペレーティングシステムデータ構造の詳細は、『SOLARIS インターナル — カーネル構造のすべて』を参照してください。

string cwd

現在のスレッドに関連付けられているプロセスの現在の作業ディレクトリ名です。

uint_t epid

現在のプローブの有効なプローブ ID (EPID) です。この整数は、特定の述語と一連のアクションによって有効化された特定のプローブを一意に識別します。

int errno

このスレッドによって直前に実行されたシステムコールから返されるエラー値です。

string execname

現在のプロセスを実行するため、exec(2) に渡された名前です。

gid_t gid

現在のプロセスの実グループ ID です。

uint_t id

現在のプローブのプローブ ID です。この ID は、DTrace によって発行された、システム内のプローブを一意に識別する識別子です。この ID を確認するには、dtrace -l を実行します。

uint_t ipl

現在の CPU でのプローブ起動時の割り込み優先レベル (IPL) を表します。Solaris オペレーティングシステムカーネルでの割り込みレベルと割り込み処理の詳細は、『SOLARIS インターナル — カーネル構造のすべて』を参照してください。

lgrp_id_t lgrp

現在の CPU をメンバーに持つ遅延グループの近傍性グループ ID です。DTrace での CPU 管理については、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。近傍性グループについては、『プログラミングインタフェース』の第 4 章「近傍性グループ API」を参照してください。

pid_t pid

現在のプロセスのプロセス ID です。

pid_t ppid

現在のプロセスの親プロセスのプロセス ID です。

string probefunc

現在のプローブの記述に含まれる関数名の部分です。

string probemod

現在のプローブの記述に含まれるモジュール名の部分です。

string probename

現在のプローブの記述に含まれる名前の部分です。

string probeprov

現在のプローブの記述に含まれるプロバイダ名の部分です。

psetid_t pset

現在の CPU が含まれているプロセッサセットのプロセッサセット ID です。詳細は、『Solaris 動的トレースガイド』の第 26 章「sched プロバイダ」を参照してください。

string root

現在のスレッドに関連付けられているプロセスのルートディレクトリ名です。

uint_t stackdepth

現在のスレッドのプローブ起動時のスタックフレームの深さを表します。

id_t tid

現在のスレッドのスレッド ID です。スレッドにユーザープロセスが関連付けられている場合、この値は、pthread_self(3C) の呼び出し結果と等しくなります。

uint64_t timestamp

ナノ秒タイムスタンプカウンタの現在の値です。このカウンタの値は、過去の任意の時点から増分しています。そのため、このカウンタは、相対計算専用です。

uid_t uid

現在のプロセスの実ユーザー ID です。

uint64_t uregs[]

現在のスレッドの、プローブ起動時のユーザーモード登録値 (保存済み) です。uregs[] 配列の使用方法については、『Solaris 動的トレースガイド』の第 33 章「ユーザープロセスのトレース」を参照してください。

uint64_t vtimestamp

ナノ秒タイムスタンプカウンタの現在の値です。このカウンタは、現在のスレッドの CPU 上での実行時間を示します。これには、DTrace の述語やアクションの実行にかかる時間は含まれません。このカウンタの値は、過去の任意の時点から増分しています。そのため、このカウンタは、相対時間計算専用です。

uint64_t walltimestamp

1970 年 1 月 1 日の協定世界時 00:00 から現在までの経過時間をナノ秒単位で示します。