述語記述における注意点
述語
記述順序に関する注意
dtrace
コマンドは,
たとえば,
リスト7 記述順序の入れ替え
/* 節 (1) */
pid$target:show_nesting:f3:entry
{
self->traced = 1;
}
/* 節 (2) */
pid$target:show_nesting:f3:return
{
self->traced = 0;
}
/* 節 (3) */
pid$target:show_nesting::entry,
pid$target:show_nesting::return
/self->traced/
{
}
このスクリプトの各節は,f3()
の開始の際に以下のように振る舞います。
- 関数
f3()
の開始なので,self->traced
を1に設定 - 関数
f3()
の開始なので,無視 self->traced
が1なので,実施=関数フロー表示
結果として,f3()
の開始」
その一方で,f3()
の終了の際に,
- 関数
f3()
の終了なので,無視 - 関数
f3()
の終了なので,self->traced
を0に設定 self->traced
が0なので,無視
開始と異なり,f3()
の終了」
もうひとつの例として,
リスト8 抑止付きの絞り込み(リスト6の再掲)
/* 節 (1) */
pid$target:show_nesting:f4:entry
{
self->traced = 1;
}
/* 節 (2) */
pid$target:show_nesting:f2:return
/self->traced/
{
self->suppressed = 0;
}
/* 節 (3) */
pid$target:show_nesting::entry,
pid$target:show_nesting::return
/self->traced && !self->suppressed/
{
}
/* 節 (4) */
pid$target:show_nesting:f2:entry
/self->traced/
{
self->suppressed = 1;
}
/* 節 (5) */
pid$target:show_nesting:f4:return
{
self->traced = 0;
}
関数f4()
に対する節(1)/(5)ではentry
/return
の順序で記述されているプローブが,f2()
に対する節(2)/(4)では逆順で書かれていることがわかります。
これは,entry
/return
の順で記述した場合,entry
プローブによるself->suppressed = 1
が実施されるため,f2()
自身がトレース採取対象から除外されてしまうのを防ぐためです。
指定の関数を採取対象に含めるか否かに応じて,
再帰呼び出しに関する注意
範囲を絞り込んだ採取の際に使用したDスクリプト
リスト9 採取範囲の絞り込み
pid$target:show_nesting:f3:entry
{
self->traced = 1;
}
pid$target:show_nesting::entry,
pid$target:show_nesting::return
/self->traced/
{
}
pid$target:show_nesting:f3:return
{
self->traced = 0;
}
先述した実行例では期待通りの結果を得られましたが,
もしも,f3()
が,self->traced = 1
実施後に再度呼ばれる,f3()
呼び出しがあっても,f3()
終了でself->traced = 0
が実施されてしまうため,
この問題を解決するためには,f3()
呼び出しの入れ子状況を正しく把握する必要があります。
そこで,
リスト10 再帰に対応した絞り込み
pid$target:show_nesting:f3:entry
{
self->traced += 1;
}
pid$target:show_nesting::entry,
pid$target:show_nesting::return
/self->traced/
{
}
pid$target:show_nesting:f3:return
{
self->traced -= 1;
}
上記スクリプトでは,self->traced
値を,f3()
呼び出しの入れ子の深さを表す値として扱っています。
これにより,f3()
の最初の呼び出しから復帰するまでは,self->traced
値が0になることがありませんので,
なお,
次回予告
次回は,