以 PDF 格式下载本书 (2302 KB)
第 22 章 sdt プロバイダ静的定義トレース (Statically Defined Tracing、SDT) プロバイダは、ソフトウェアプログラマが正式に指定した位置でプローブを作成します。プログラマは、SDT 機構を利用して、DTrace ユーザーにとって重要な箇所をプローブの設定位置として意識的に選択できます。さらに、このプローブに、その位置についてよくわかるようなプローブ名を付けることができます。Solaris カーネルにも少数の SDT プローブが定義されており、将来はさらに追加される予定です。DTrace はまた、ユーザーアプリケーション開発者を対象に、静的プローブを定義する機構を提供しています。これについては、第 34 章ユーザーアプリケーション向けの静的に定義されたトレースで説明します。 プローブ表 22–1 は、Solaris カーネルに定義されている SDT プローブです。これらのプローブの名前の安定性とデータの安定性は、どちらも「非公開」です。これは、ここでの記述がカーネルの実装を反映しているため、確約されたインタフェースとして推測されるべきでないからです。DTrace の安定性機構の詳細については、「安定性」を参照してください。 表 22–1 SDT プローブ
例以下は、1 秒に 1 回のペースでコールアウトの動作を調べるスクリプトです。 #pragma D option quiet
sdt:::callout-start
{
@callouts[((callout_t *)arg0)->c_func] = count();
}
tick-1sec
{
printa("%40a %10@d\n", @callouts);
clear(@callouts);
}
この例を実行すると、そのシステム内で timeout(9F) をよく使用するユーザーがわかります。次の出力例を参照してください。
timeout(9F) インタフェースは、単一のタイマーの有効期限を出力するだけです。timeout() のインターバルタイマー機能を利用する場合、通常 timeout() ハンドラから timeout を再インストールします。以下に例を示します。 #pragma D option quiet
sdt:::callout-start
{
self->callout = ((callout_t *)arg0)->c_func;
}
fbt::timeout:entry
/self->callout && arg2 <= 100/
{
/*
* In this case, we are most interested in interval timeout(9F)s that
* are short. We therefore do a linear quantization from 0 ticks to
* 100 ticks. The system clock's frequency — set by the variable
* "hz" — defaults to 100, so 100 system clock ticks is one second.
*/
@callout[self->callout] = lquantize(arg2, 0, 100);
}
sdt:::callout-end
{
self->callout = NULL;
}
END
{
printa("%a\n%@d\n\n", @callout);
}
このスクリプトを実行し、しばらく待ってから Control-C キーを押すと、次のような出力が得られます。
この出力からわかるように、uhci(7D) ドライバ内の uhci_handle_root_hub_status_change() は、このシステム上のもっとも短い間隔で呼び出されるインターバルタイマー (システムクロック刻みに合わせて呼び出される) です。 割り込みアクティビティに関する情報は、interrupt-start プローブから得ることができます。次の例では、ドライバ名を指定して、割り込みハンドラの実行にかかった時間を調べています。 interrupt-start
{
self->ts = vtimestamp;
}
interrupt-complete
/self->ts/
{
this->devi = (struct dev_info *)arg0;
@[stringof(`devnamesp[this->devi->devi_major].dn_name),
this->devi->devi_instance] = quantize(vtimestamp - self->ts);
}
このスクリプトを実行すると、次のような出力が得られます。
SDT プローブの作成デバイスドライバの開発者は、Solaris ドライバ内に独自の SDT プローブを作成したいと思うことがあるかもしれません。SDT プローブが無効にされている状態は、無操作マシン命令がいくつかある状態と実質的に同じです。したがって、必要に応じて SDT プローブをデバイスドライバに追加してかまいません。これらのプローブがパフォーマンスに悪影響を及ぼさないかぎり、出荷コード内に残しておいてもかまいません。 プローブの宣言SDT プローブを宣言するときは、<sys/sdt.h> のマクロ DTRACE_PROBE 、DTRACE_PROBE1、DTRACE_PROBE2、 DTRACE_PROBE3、DTRACE_PROBE4 を使用します。SDT ベースのプローブのモジュール名は、カーネルモジュール名を反映しています。また、関数名は、そのプローブの関数を表しています。プローブ名は、DTRACE_PROBEn マクロで指定された名前によって決まります。この名前に 2 つの連続する下線 (__) が含まれていない場合、マクロに指定されたとおりのプローブ名になります。この名前に 2 つの連続する下線が含まれている場合、プローブ名では、この下線部分がダッシュ 1 個 (-) に変換されます。たとえば、DTRACE_PROBE マクロに transaction__start と指定されている場合、SDT プローブ名は transaction-start になります。このような置き換えが行われるので、C コード内のマクロ名が有効な C 識別子でなくても、文字列を指定しないで使用できます。 カーネルモジュール名と関数名は、DTrace によって、プローブを識別する組に含められます。したがって、名前空間の衝突を避けるためにプローブ名にこの情報を指定する必要性は特にありません。インストール済みのプローブと、DTrace ユーザーが確認できるフルネームを一覧するには、ドライバ上で dtrace -l -P sdt -m module (module はドライバ) を実行します。 プローブ引数各 SDT プローブの引数は、対応する DTRACE_PROBEn マクロ参照に指定された引数になります。引数の数は、どのマクロを使ってプローブを作成したかによって異なります。 たとえば、DTRACE_PROBE1 は引数を 1 つ、DTRACE_PROBE2 は 2 つ (以下同様) 指定します。SDT プローブを宣言するときは、ポインタを間接参照せず、プローブ引数内の大域変数からロードしないようにすれば、無効時のプローブの影響を最小限に抑えることができます。ポインタの間接参照も、大域変数のロードも、D のプローブ有効化アクション内で安全に実行できます。こうしたアクションが必要なときには要求してかまいません。 安定性以下の表に、SDT プロバイダの安定性を DTrace の安定性機構に従って示します。安定性機構の詳細については、第 39 章安定性を参照してください。
|
|||||||||||||||||||||||||||||||||||||||||||