制御フローのための述語の使用
実行時の安全性を確保するため、DとCやC++などの他のプログラミング言語の主な違いの1つとして、Javaプログラミング言語に、if文やループなどの制御フロー構造がないことがあげられ。 Dプログラム節は、固定量のデータ(オプション)をトレースする単一の直線的な文のリストとして作成されます。 Dは、述語と呼ばれる論理式を使用して、条件付きでデータをトレースし、制御フローを変更する機能を提供します。 このチュートリアルでは、Dプログラムの制御に述語を使用する方法を示します。
述語の動作を理解するために、10秒カウントダウン・タイマーを実装するDプログラムを作成します。 このプログラムを実行すると、10からカウント・ダウンし、メッセージを出力して終了します。 このプログラムでは、変数と述語を使用して、経過時間と出力内容を評価します。
このチュートリアルでは、BEGINプローブを使用して、変数整数iをカウントダウン開始の10に初期化します。 次に、tick-1secプローブを使用して、プログラムに毎秒1回起動するタイマーを実装します。 countdown.dでは、tick-1secプローブ記述が、述語と関数リストの異なる2つの個別の節で使用されています。 述語は、前後をスラッシュ//で囲まれた論理式で、プローブ名と、節の文リストが入っている中カッコ{}の間にあります。
最初の述語は、iがゼロより大きいかどうか(タイマーがまだ実行中かどうか)をテストします。
profile:::tick-1sec
/i > 0/
{
trace(i--);
}
関係演算子>は、「より大きい」を意味し、偽の場合は整数値0、真の場合は1を返します。 iがまだ0になっていない場合、スクリプトではiをトレースし、--演算子を使用して1ずつ値を減らします。
2番目の述語は、==演算子を使用して、iが0 (カウントダウンが完了した)の場合に真を返します。
profile:::tick-1sec
/i == 0/
{
trace("blastoff!");
exit(0);
}
2番目の節では、文字列定数と呼ばれる二重引用符で囲まれた一連の文字にtrace関数を使用して、カウントダウンが完了したときの最後のメッセージを出力します。 次に、exit関数を使用して、すべてのトレースを終了し、最終的なデータの消費、集積体の出力(必要な場合)、シェル・プロンプトに戻る前のクリーン・アップの実行などの残りのタスクを実行します。
例1-1 あるプロセスIDのシステム・コールを監視するために述語を使用する方法
あるプロセスIDのシステム・コールをトレースするDプログラムを作成するには、述語を使用して、トレースするプロセスIDと一致するようにデフォルトのトレース関数を制限します。
syscall:::entry
/pid == 2860/
{
}
この例では、組込み変数pidが特定のID(この例では2860)と一致するように評価されます。 さらに、このスクリプトはシェルのマクロ変数を利用するように変更すると、拡張性が向上して、実行時に任意のプロセスIDに対して実行できるようになります。 次のようにスクリプトを編集し、strace.dsというファイルに保存します:
#!/usr/sbin/dtrace -s
syscall:::entry
/pid == $1/
{
}
ファイル・モードを変更して、実行可能にします。
sudo chmod +x strace.ds
これで、このスクリプトを使用して、システムでいずれかのプロセスによって行われたすべてのシステム・コールを監視できます。 たとえば、このスクリプトを実行して、cronデーモンによるシステム・コールを監視できます:
sudo ./strace.ds $(pidof /usr/sbin/crond)