目次

DTrace

ここはマニュアル抜粋のメモ。あとで使うなとおもった内容を一式抜粋してます。 ページ数がある場合は、日本語マニュアルのページ数になってます。

samples

文法とかはマニュアル読めって感じで、例によって自分で使ったのを載せる方向で。

プロセスのuserland symbol trace

以下のコマンドが基本型。ユーザシンボルのtraceであり、対象execnameに含まれるシンボルだけが trace出力の対象になる。このため、runtime libraryの呼び出し等も含めたい場合、probeの probemodule(左から2項目)の指定を適切に変える必要がある。(-qを指定すると出力がぐちゃぐちゃに なるので注意。)
dtrace -c "<execname> <args>" -F -n 'pid$target:<execname>::entry,
  pid$target:<execname>::return'

user symbolの関数の場合でも :::enterのarg[0-9]はその関数の引数になっているので、内容のdumpが可能である。

子プロセスのexec/waitpidモニタ

procプロバイダでfork1付近をモニタしてみた。第1引数で対象とするexecnameを指定すると、 それがfork/execする子プロセスの生成付近をみて、終了時にsi_codeを拾ってログ出力する。
で、びみょぃのが、procプロバイダのexec/exec-xxx probeのマニュアル上の説明では exec probeはfork前のstate、exec-xxx probeではfork後のstateを持つと書いてあるのだが、 実際に書いて調べてみる限りではexec probeが呼ばれた時点で子プロセスのstateになっていた。
#!/usr/sbin/dtrace -qs
/*
probe           args[0]         args[1]         args[2]
create          psinfo_t *
exec            char *
exec-failure    int
exit            int
fault           int             siginfo_t *
start
*/

dtrace:::BEGIN
{
        ename = $$1;
        printf("target execname : %s\n", ename);
}

this watchid;
this chldname;
proc:::exec
/ execname == ename /
{
        watchid = curpsinfo->pr_ppid;
        chldname = args[0];
}

proc:::exec-success
/ ppid == watchid /
{
        flag[watchid] = 1;
}

proc:::exec-failure
/ ppid == watchid /
{
        flag[watchid] = 0;
}

proc:::exit
/ ppid == watchid && flag[watchid] == 1 /
{
        printf("[invoked by %d] %s si_code is %d\n",
                ppid, chldname, args[0]);
}
proc:::exitのhookは未完成。

ホントはwaitpid()とかで拾える子プロセスの戻り値を拾いたいのだが、 syscall::wait:がwaitid(2)とかwaitpid(3C)あたりなのかよくわからん。

それでも上記のサンプルを載せたのはproc providerの説明と実際が一致してなかったからだったりする。

syscall monitor

他に方法もあるだろうが、引数に対応するsyscall::[func]:entryをmonitorするスクリプト。 引数を取って使うと言う部分のために載せてみた。
#!/usr/sbin/dtrace -qs

self string t;

dtrace:::BEGIN 
{
        t = $$1;
        printf("target : %s\n",t);
}

syscall:::entry
/ probefunc == t /
{
        printf("[%d]%s %s\n",pid, execname, t);
        printf("--------------\n");
}

file io monitor

アプリケーションの動作を調べる上で、特定ファイルに対するI/Oが発生した際の ustackが 見たかったので書いてみた。対象とするファイルをコマンドライン引数で指定する。 io providerのargs[0]からioを、args[2]からファイルの情報を拾っている。
なお、args[2]->fi_nameはパス名ではなく、ディレクトリエントリ上に登録されている ファイル名になるので、パス名だとmatchしないので注意。
io:::start
/ args[2]->fi_name == $1 /
{
        printf("[%d]%s %s %s\n", pid, execname,
                args[0]->b_flags & B_READ ? "read" : "write",
                args[2]->fi_pathname);
        ustack();
        printf("--------------\n");
}
i/o providerの場合、ファイルをwriteするときはmonitorするのにreadするときは monitorできないのはなんでだろか。。。

syscall::open monitor

こりゃ DTraceぃぃゎーと思ったきっかけになったのが下記。 これだとマニュアルに載ってる気がするが、記念品ってことでw

open(2)の第1引数がさすパス名文字列を、直だと当然ただの アドレスなので、copyinstr()で参照先をstringにして dumpしてる。

syscall::open:entry
{
        printf("[%d]%s open %s\n",
        pid, execname, copyinstr(arg0));
        ustack();
        printf("--------------\n");
}

dtrace(1M)コマンドライン引数

知りたいものだけを適当にメモ
optdesc
-P provier -m module -f function -n nameprovider:module:function:name
表示フィルタは -n ::hoge:hoge みたいに評価させてfilterするのがぃぃ
-n '1 liner'
-Fpragma D option flowindent
-c <cmd args>exec cmd under dtrace

DTraceマクロ変数一覧(p.183)

抜粋の表のままです。
namedesc
$[0-9]マクロ引数
$targetターゲットプロセスID。-cで実行したときの実行されたコマンドのPID
$egid実効グループID
$euid実効ユーザID
$gid実グループID
$pidプロセスID(dtrace自身のpid)
$uidユーザID
$pgidプロセスグループID
$ppid親プロセスID
$sidセッションID
$taskidタスクID

DTrace組込み変数一覧(p.67-)

抜粋の表とは順番を適当に変えてます。
namedesc
int64_t arg0 ・・ arg9probeに渡される最初の10個の引数の64bit int表現。10より足りない部分は0になる。
args[]probeに渡された型付き引数。arg[0-9]と一緒だが、probeの引数に合わせた型になる。これはprobe毎に何があるか異なるので、個々にマニュアルを見るべし。
uint64_t timestampDTraceの処理時間もカウントしたnsのcounter
uint64_t vtimestampDTaceの処理時間をカウントしないnsのcounter
uint64_t walltimestampUNIX時間なtick timer
string probenamedtrace -lの末尾。probeの名前
string probefuncdtrace -lの後から2個目。probeの関数部
string probemoddrace -lの3項目。probeのmodule部
string cwdthrのCWD
pid_t pid自身のPID
pid_t ppid親プロセスのPID
int errnoerrno
string rootルートディレクトリ。chrootしてなきゃ /
uint_t stackdepthstackframeの深さ
id_t tidthrのID
uint64_t uregs[]なんかわからん。chap33参照
gid_t gidgid
uint_t uideffective uid
uint_t epidprobeが呼ばれたときのeffective pid
uintptr_t caller名前の通り、PCの参照先
chipid_t chipCPUチップ識別子
processorid_t cpuCPU識別子
cpuinfo_t *curcpuCPU情報
lwpsinfo_t *curlwpsinfothrにbindしているLWPの状態。proc(4)を参照
psinfo_t *curpsinfothrに関連づけられたプロセスの状態。proc(4)を参照
kthread_t *curthreadthr/LWPにbindされたkthrのアドレス。
uint_t idprobeのid
uint_t ipl割り込みレベル
lgrp_id_t lgrp応答時間グループのグループID
psetid_t pset現在のCPUが含まれるpsrsetのID

関連情報

DTT

OpenSolaris.orgのsub projectにDTrace Toolkitてのがある。 Solaris10の場合、/usr/demo/dtrace配下に、DTraceのマニュアルにあるスクリプトが一式入っているが、 マニュアルにあるものなので、実戦投入wはなかなかである。

install用のscriptが同梱されている tar.gzが提供されていて、/opt/DTT配下に展開される。 2007-11-29現在で ver0.9.9である。 結構な数のD scriptがあるので、Solarisバンドル以外のサンプルとして見てみる価値があるし、 実際の調査でそのまま使える気がする。

公式にもリンクのあるこのサイトで、 DTTも含めたDTraceの紹介プレゼン(odpのみで翻訳版もある。出来ればpdfも置いてほしいが・・・  翻訳されたのとおもいきや、リンク先のファイルは爽やかにファイル名だけが異なるoriginal版の模様です と思いきや、Day2だけを翻訳したそうです)がある。 紹介プレゼンは3部構成(DTrace紹介、DTT紹介、実際の例)になっているので、 他の人に紹介する際の資料のベースとしてこのプレゼンはなかなか使える。

misc

雑多なリンク

Perl5.10.1 /w DTrace


Last-modified: 2010-04-24 19:16:29