DTrace で検査点を有効にする2009年02月20日 12時10分51秒

dtrace はプロバイダ名、モジュール名、関数名、プローブ名の四つの要素から検査点を絞り込む。一番利用頻度が高いのは、dtrace -n provider:module:function:name の形だろう。

これらの四つの要素は、dtrace -l で調べられる。


$ kldload dtraceall
$ dtrace -l
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR
    4   dtmalloc                                                 fbt malloc
    5   dtmalloc                                                 fbt free
    6   dtmalloc                                              cyclic malloc
    7   dtmalloc                                              cyclic free
    8   dtmalloc                                             solaris malloc
...
34294        fbt             tmpfs                    tmpfs_pathconf entry
34295        fbt             tmpfs                    tmpfs_pathconf return
34296        fbt             tmpfs                     tmpfs_symlink entry
34297        fbt             tmpfs                     tmpfs_symlink return
34298        fbt             tmpfs                       tmpfs_mkdir entry
34299        fbt             tmpfs                       tmpfs_mkdir return

これらの中から追跡したい動作を探しだし、有効にする。

基本的な検査点の指定方法は、名前を使う。検査点の名前のみ指定する場合は、entry を指定しても、return を指定しても大差はない。


$ dtrace -n fbt:tmpfs:tmpfs_mkdir:entry
dtrace: description 'fbt:tmpfs:tmpfs_mkdir:entry' matched 1 probe

これで、fbt プロバイダの中の tmpfs モジュールの中の tmpfs_mkdir 関数に入る時に、dtrace が出力を出す。

これだけでも充分に使い物になる場合が多い。例えば、ソースコードを眺めて大体の動作は掴めた後に、実際に呼ばれるのを確かめるのに使える。


$ dtrace -n fbt:tmpfs:tmpfs_mkdir:entry
dtrace: description 'fbt:tmpfs:tmpfs_mkdir:entry' matched 1 probe
^Z
Suspended
$ bg
[1]    dtrace -n fbt:tmpfs:tmpfs_mkdir:entry &
$ mkdir /mnt/ufs/dir
$ mkdir /mnt/tmpfs/dir
$ CPU     ID                    FUNCTION:NAME
  0  34298                tmpfs_mkdir:entry 
$ rmdir /usr/tmp/dir
$ fg
dtrace -n fbt:tmpfs:tmpfs_mkdir:entry
^C


いつ出力が起きているかを具体的に示すために、dtrace を後ろに追いやった。Ctl-C で dtrace を終了する。

一度に二つの検査点を指定することも出来る。


$ dtrace -n fbt:tmpfs:tmpfs_mkdir:entry,tmpfs_create:entry
dtrace: description 'fbt:tmpfs:tmpfs_mkdir:entry,tmpfs_create:entry' matched 2 p
robes

4 つの要素のうち、前半は省略可能だ。例えば、::tmpfs_create:entry と指定すると、tmpfs_create:entry と指定したのと同じになる。tmpfs 関数なので他のプロバイダやモジュールと名前が衝突する事はないが、open などだと、複数の検査点が出来る。

これと同じような事をしようとすると、printf を入れたりデバッガを使ったり出来る。しかし、printf は簡単だが、再コンパイルとインストールを何回も繰り返す事になる。デバッガでも strip されているとライブラリやらバイナリやらを作り直す必要がある事も多く、またカーネルデバッガは色々と敷居が高くなる。dtrace -n 名前 を使うだけでこれらの手間から開放され、コードを追いかける効率が格段と上がった。