言語およびスクリプト
ProbeVue は、プローブを使用して問題判別とパフォーマンス分析を行います。 プローブ は、正常なシステム処置を中断して現行コンテキストとシステム状態を検査し、それらの情報を取得するソフトウェア・メカニズムです。
これは、一般的にトレースとも呼ばれます。 トレース・アクションまたはプローブ・アクションは、通常、グローバル情報とコンテキスト固有情報の現行値をトレース・バッファーに書き込んで情報を収集します。 この情報はトレース・データと呼ばれます。 通常、システムはトレース・バッファーからデータを読み取り、システムのユーザーがそのデータを使用できるようにする機能を備えています。
プローブ・ポイント は、プローブできる正常なシステム・アクティビティーでのポイントを表します。 動的トレースでは、プローブ・ポイントをトレースする場合を除いて、プローブ・ポイントにプローブは付加されません。 プローブを使用可能 にするとプローブがプローブ・ポイントに付加され、プローブを使用不可 にするとプローブがプローブ・ポイントから除去されます。 システム・アクティビティーで使用可能なプローブ・ポイントに到達し、トレース・アクションが実行されると、プローブがトリガー または起動 されます。
ProbeVue は、大きく 2 つに分類された次のプローブ・ポイントをサポートしています。
- プローブ・ロケーション
- 一部のトレース・アクションが実行されるユーザー・コードまたはカーネル・コードのロケーション。 プローブ・ロケーションにある使用可能なプローブは、スレッド実行コードがこのロケーションに到達すると起動します。
- プローブ・イベント
- 一部のトレース・アクションが実行されるイベント。 プローブ・イベントは特定のコード・ロケーションに容易にマップされません。 プローブ・イベントを示す使用可能なプローブは、このイベントが発生したときに実行されるように構成されます。
ProbeVue は、プローブ・ポイントをそのタイプでも区別します。 プローブ・タイプは、いくつかの共通特性を共有する一連のプローブ・ポイントを表します。例えば、システム・コールのエントリーと終了を表すプローブ・ポイントや、システム統計に対する更新を示すプローブ・ポイントなどです。 プローブをタイプごとに区別すると、さまざまな種類のプローブ・ポイントが構造化されます。
ProbeVue では、各プローブ・タイプにプローブ・マネージャーを関連付ける必要があります。 プローブ・マネージャーは、同じプローブ・タイプの一連のプローブ・ポイントを定義して提供するソフトウェア・コードです。例えば、システム・コール・プローブ・マネージャーがあります。
Vue プログラミング言語
Vue プログラミング言語では、ProbeVue に対するトレース指定が可能です。 Vue スクリプトまたは Vue プログラムは、Vue で作成されたプログラムです。 Vue スクリプトは次の目的で使用できます。
- プローブを動的に使用可能にするプローブ・ポイントを識別する。
- プローブを起動するために満たす必要がある条件 (ある場合) を指定する。
- 実行されるアクションを指定する (収集するトレース・データを含む)。
すなわち、Vue スクリプトは、トレースする場所、タイミング、および項目を ProbeVue に指示します。 Vue スクリプトには「.e」のファイル・サフィックスがあり、他のファイル・タイプと区別されます。
Vue はプログラミング言語でもあり、スクリプト言語でもあります。これは動的トレースの専用言語です。 Vue は、動的トレースに最も有効な C とスクリプト構文のサブセットをサポートしています。
C のエレメント
Vue は C のサブセットをサポートしています。次の表では、指定された C キーワードに対する ProbeVue コンパイラーのサポート状況を説明します。 すべての C キーワードが Vue で制限付きのままです。 これらのキーワードを変数名または他のシンボルとして使用しても構文エラーのフラグは立ちませんが、このような使用の動作は未定義です。
| サポートされています。 | ヘッダー・ファイルまたは宣言セクションで許可される | サポートされない |
|---|---|---|
| char | auto | break |
| double | const | case |
| else | extern | continue |
| enum | register | default |
| float | static | do |
| if | typedef | for |
| int | volatile | goto |
| long | switch | |
| return | while | |
| short | ||
| signed | ||
| sizeof | ||
| struct | ||
| union | ||
| unsigned | ||
| void |
ここでは、Vue がサポートする一連の C 機能について説明します。
- ステートメント
- すべての C ステートメント (ループ・ステートメントと一部の制御フロー・ステートメントを除く)。
- 演算子
- すべての C 単項、2 項、3 項演算子 (コンマ演算子を除く)。 演算子優先順位と結合順序は、C 言語のルールに従います。
- データ型
- ほとんどの有効な C-89 定義変数型。制限に従って型を宣言するためのすべてのステートメントとキーワード (struct、union、enum、typedef など) が含まれます。 これにはカーネルまたはアプリケーションの変数とパラメーターの型が含まれます。 注: Vue には、スコープとストレージ・クラスに関する独自のルールがあります。
- 型変換
- 暗黙的型変換および明示的変換 (型キャスト)。
- サブルーチン
- サブルーチンを呼び出し、パラメーターを関数に渡すための構文。 ただし、呼び出し可能な関数に対する制限があります。
- 変数名
- 変数の命名規則は、C の ID ルールに従います。 変数クラス名が変数名の先頭に付いている場合は、完全な変数指定にコロンを指定できます。
- ヘッダー・ファイル
- カーネル・グローバル変数の型またはアプリケーションとカーネルの関数のプロトタイプを明示的に宣言するためにヘッダー・ファイルを指定できます。 ヘッダー・ファイルの指定方法には、いくつかの制限があります。
- 区切り子
- すべての C 区切り子がサポートされており、そのルールが適用されます。 このため、ステートメントはセミコロン (;) 文字で区切る必要があります。 すべての C 空白文字ルールに従います。
- リテラル
- 文字列 (二重引用符 (") を使用)、文字リテラル (単一引用符 (') を使用)、8 進数および 16 進数の整数、および特殊文字 (¥n や ¥t のエスケープ・シーケンスなど) の表記。
- コメント
- C および C++ 形式のコメント。 コメントは節の内部と外部の両方に挿入できます。 # 文字で始まる行は無視されます。 この文字を使用してコメント行を指定しないでください。
C 言語との相違点
Vue には、一部の C 機能に対して異なる動作があります。 効率性を保持するか、カーネル内で Vue スクリプトを正常に実行して、プローブされるプロセスに影響を与えないために、いくつかの制限があります。
- ループ・ステートメント
- Vue スクリプトでは、ループ・ステートメントは受け入れられません。 これは Vue プローブが永久に完了しないのを防ぐための予防措置です。
- 条件付きフロー・ステートメント
- Vue スクリプトでは、"if-else" 形式の制御フロー・ステートメントのみ受け入れられます。 "if" ステートメントを適切に使用して、ほとんどの条件付き論理フローを実行できます。 Vue スクリプトで述部を使用すると、高水準条件付き論理をより効率的に実行できます。
- 戻りステートメント
- Vue では、アクション・ブロックの実行がすぐに終了することを通知するために、戻りステートメントが受け入れられます。 ただし、Vue のアクション・ブロックには戻り値がないため、戻りステートメントは Vue の式を取りません。
- サブルーチン
- Vue スクリプトは、AIX® システムまたは汎用ユーザー・ライブラリーで提供される関数にはアクセスできません。 プローブ内から呼び出し可能なアーカイブ (関数のライブラリー) またはユーザー関数を作成することはできません。 その代わりに、特殊な内部ライブラリーが用意されており、動的トレース・プログラムに有用な一連の関数を使用できます。
- 浮動小数点
- カーネル・プローブ・ポイントに関連した節では、浮動小数点変数は受け入れられません。 浮動小数点変数を使用できるのは、単純な代入ステートメント内、およびデータを印刷する Vue 関数に対するパラメーターとしてのみです。 Vue 言語での浮動小数点変数のサポートは、その収集に限定されています。
- 変数の変更
- 代入ステートメントの左辺では、外部変数は受け入れられません。すなわち、これらの変数は Vue スクリプトで変更できません。
- ヘッダー・ファイル
- Vue では、Vue スクリプト自体にヘッダー・ファイルを明示的に組み込むことはできません。 その代わりに、組み込むヘッダー・ファイルの名前をコマンド・ライン引数を使用して probevue コマンドに渡す必要があります。 ヘッダー・ファイル内の C プリプロセッサーの演算子またはディレクティブはすべて無視されます。 これにより予期しない動作が発生する可能性があります。 これを回避するには、ヘッダー・ファイルをハンド・コーディングするか、関連ヘッダー・ファイルのセットに直接 C プリプロセッサーを明示的に実行して、後処理されたヘッダー・ファイルを生成して組み込みます。 関数プロトタイプと構造体/共用体の定義がプローブ節の開始前の先頭に挿入されている場合は、これらを Vue スクリプト自体に含めることができます。
- C プリプロセッサー
- C プリプロセッサーの演算子、マクロ定義、行またはプラグマ・ディレクティブ、および定義済みマクロ名は無視されます。
- ポインター演算
- Vue では、スクリプト変数へのポインターは受け入れられません。 例えば、スクリプト変数のアドレスを取ることはできません。 ただし、カーネル変数のアドレスは取ることができ、Vue ポインター変数およびこのポインター変数を使用できるポインター演算に代入することができます。
- その他
-
- 3 文字表記は受け入れられません。
- コンマ演算子は受け入れられません。
- 宣言ステートメントには初期化を指定できません。
probevue コマンド
probevue コマンドは、動的トレース・セッションまたは ProbeVue セッションを開始します。 probevue コマンドは、Vue スクリプトをファイルから読み取った入力またはコマンド・ラインからの入力として取り、ProbeVue セッションを活動化します。 ProbeVue セッションで収集されたトレース・データは、コマンド・ラインで渡されたオプションどおりに、端末に出力するか、ユーザー指定のファイルに保存することができます。
ProbeVue セッションは、端末で Ctrl-C を押すか、Vue スクリプトから終了アクションが実行されるまでアクティブのままです。
probevue コマンドが呼び出されるたびに、別々の動的トレース・セッションが活動化されます。 一度に複数のトレース・セッションを活動化できますが、各セッションはそのセッションで収集されるトレース・データのみ提供します。 並行セッションは、通常、相互のセッションを認識していません。
probevue コマンドの実行は特権操作であるため、root 以外のユーザーが動的トレース・セッションを開始するには特権が必要です。
Vue スクリプト
Vue スクリプトは、オプションの宣言セクションとその後の 1 つ以上の節から構成されます。 これらの節は Vue スクリプトに任意の順序で指定できます。 Vue スクリプトの標準的なレイアウトを次に示します。
| 宣言 | 例 |
|---|---|
| オプションの BEGIN 節 | |
| 1 つ以上のプローブ節 | |
| オプションの END 節 | |
オプションの宣言セクションは、変数型とグローバル変数の宣言に使用できます。 このセクションには実行可能ステートメントを含めることはできません。
Vue スクリプトの各節は、次の 3 つのエレメントから構成されます。
- プローブ・ポイント指定
- プローブ・ポイント指定は、動的に使用可能にする一連のプローブ・ポイントを表します。 これは 1 つ以上のプローブ・ポイント組で構成されます。このストリングの合計長は 1023 文字に制限されます。
- アクション・ブロック
- アクション・ブロックは、プローブが起動したときに実行するプローブ・アクションのシーケンスを表します。
- オプションの述部
- 述部 (ある場合) は、プローブがトリガーされたときに検査する条件を表します。 節のプローブ・アクションを実行するには、述部が TRUE に評価されなければなりません。
Vue スクリプトには、コメントを含めることができます。 コメントは Vue スクリプトの任意の場所 (Vue スクリプトの先頭、2 つの Vue 節の間、または Vue 節の中) に挿入できます。
宣言セクション
- 型、構造体、共用体、および列挙型の定義
- プローブされる関数の関数プロトタイプ宣言
- スクリプトでアクセスされるグローバル変数とカーネル変数の宣言
このセクションには、すべての形式の変数初期化など、実行可能ステートメントを含めることはできません。
Vue の宣言と定義は、通常、C 言語の C-89 言語仕様の構文に準拠しますが、Vue 固有の制限もあります。 また、Vue には、変数の Vue クラスを指定するための独自のデータ型と特殊なキーワードがいくつかあります。
プローブ・ポイント指定
プローブ・ポイント指定は 1 つ以上のプローブ・ポイント組で構成されます。 それぞれのプローブ・ポイント組は、その実行でプローブ・アクションをトリガーするコード・ロケーション、またはその発生でプローブ・アクションをトリガーするイベントを表します。 複数のプローブ・ポイントを同じプローブ・アクションのセットと述部 (ある場合) に関連付けることができます。これは Vue 節の先頭にプローブ組のリストをコンマで区切って指定します。
以下に、サポートされるプローブ・タイプの例をいくつか示します。
- ユーザー関数エントリー・プローブ (uft プローブ)
- システム・コール・エントリー・プローブまたは終了プローブ (syscall プローブ)
- 特定の時間間隔で起動するプローブ (interval プローブ)
サポートされるプローブ・タイプの完全なリストについては、プローブ・マネージャーのセクションを参照してください。
プローブ・ポイント組は、プローブ・ポイントを一意的に識別する、コロンで区切られたフィールドの番号付きリストです。この形式は次のとおりです。ただし、通常、ロケーション・フィールドは、プローブ・ポイントがプローブ・ロケーションである場合のみ指定されます。
@@ <probetype>:
<one or more probetype-specific fields separated by colons>:<location>
プローブ・マネージャーは、プローブ・ポイント組のプローブ型固有フィールドの許容値とプローブ組の長さを定義します。 ただし、プローブ・マネージャーは、プローブ・ポイント組を定義する際に以下の一般ルールに従います。
- それぞれのプローブ・ポイント組は、少なくとも 3 組である。すなわち、最低 3 フィールドが必要です。
- 最初のフィールドは必ずプローブ・タイプ (すなわち、そのプローブ・マネージャー) を表す。
- プロセス固有のトレースをサポートするプローブ・マネージャーでは、2 番目のフィールドはプロセス ID でなければならない。
- 関数のエントリー・プローブまたは終了プローブをサポートするプローブ・マネージャーでは、ロケーション・フィールド (最後のフィールド) で entry または exit キーワードを使用しなければならない。
- フィールドはコロン (:) 記号で区切る。
- プローブ・ポイント組のフィールドのアスタリスク (*) 記号は、そのフィールドに指定可能なすべての値と一致することを表します。 例えば、syscall プローブ・マネージャーでは、特定のプロセスのシステム・コール、およびすべてのプロセスのシステム・コールをプローブできます。 前者の場合、2 番目のフィールドは、プローブするプロセスのプロセス ID でなければなりません。 後者の場合、すべてのプロセスをプローブするには、2 番目のフィールドは (*) 記号でなければなりません。 フィールドに対する 2 番目のアスタリスク記号の使用では、将来的により細かいプローブが可能になる一方で、既存スクリプトとのバイナリー互換性が保持されます。 例えば、uft プローブ・マネージャーでは、現在 3 番目のフィールドがアスタリスクでなければなりません。 将来的に、3 番目のフィールドにモジュール名がサポートされ、そのモジュールに定義された関数のみにプローブを限定できます。
- プローブ指定の最大長は 1023 文字です。
次に例を示します。
- @@uft:34568:*:foo:entry
- ID が 34568 のプロセスでの foo と呼ばれる任意の関数へのエントリーのプローブ。 3 番目のフィールドにあるアスタリスクは、foo 関数がプロセスの任意のモジュールに存在する場合にプローブされることを示します。
- @@syscall:*:read:exit
- read システム・コールの終了のプローブ。 アスタリスクは、すべてのプロセスの read システム・コールがプローブされることを示します。
- @@interval:*:clock:500
- 500 ミリ秒 (壁時計時刻) ごとに起動するプローブ。 アスタリスクは、将来的により細かいプローブ・ポイントをサポートするためのプレースホルダーです。
プロセスのプロセス ID は、Vue スクリプトが作成された時点では不明である場合が多いです。 Vue では、プローブ指定の 2 番目のフィールドまたは Vue スクリプト内の任意の場所 (述部セクションなど) にプロセス ID をハードコーディングしないようにするために簡単な方法を提供しています。
1 つの Vue スクリプトには、ユーザー・スペースまたはカーネルの複数のプロセスからのプローブ・ポイントを含めることができます。 生成されたトレース出力は、常に時間順に表示されます。
Vue は、プローブ・マネージャーで定義される通常のプローブ・ポイントに加えて、2 つの特殊なプローブ・ポイントをサポートしています。 各 Vue スクリプトに @@BEGIN プローブ・ポイントと @@END プローブ・ポイントを含めることができ、@@BEGIN プローブ・ポイントはプローブを使用可能にする前に実行する必要があるアクションを示し、@@END プローブ・ポイントはトレースが終了した後に実行するアクションを示します。
アクション・ブロック
アクション・ブロックは、関連したプローブ・ポイントがトリガーされたときに実行するトレース・アクションを表します。 サポートされるアクションはトレース・データの収集とフォーマットに限定されず、Vue 言語のすべての機能を利用できます。
Vue のアクション・ブロックは、プロシージャー型言語のプロシージャーに似ています。 これは順番に実行されるステートメントのシーケンスで構成されます。 実行のフローは基本的に順次です。 例外として、「if-else」ステートメントを使用した条件付き実行が可能となり、「return」ステートメントを使用してアクション・ブロックから制御が戻されます。 また、Vue はスクリプト全体を終了し、トレース・セッションを終了する exit 関数をサポートしています。 Vue および C 言語ステートメントにはループの構造がないため、「for」、「do」、「goto」などはサポートされていません。
プロシージャー型言語のプロシージャーとは異なり、Vue のアクション・ブロックには出力または戻り値がありません。 また、一連の入力パラメーターに対する固有のサポートもありません。 その一方で、アクション・ブロック内でプローブが開始するポイントのコンテキスト・データにアクセスできます。 例えば、プローブ・ポイントが関数のエントリー・ポイントにある場合に、その関数に渡されるパラメーターを Vue 節のアクション・ブロック内で参照できます。
述部
プローブ・ポイントの節の実行を条件付きで行う必要がある場合は、述部を使用します。 述部セクションは、プローブ指定セクションのすぐ後にある when キーワードによって識別されます。 述部自体は、通常の C 形式の条件式と括弧で構成されます。
when ( <condition> )when ( __pid == 1678 )Vue スクリプトの例
Vue スクリプトの例を以下に示します。
/* Global variables are auto-initialized to zero */ [1]
int count; /[2]
/*
* File: count.e
*
* Count number of times the read or write system call is entered
* by process with Id 400
*/
@@BEGIN
{
printf("Start probing¥n");
}
@@syscall:*:read:entry, @@syscall:*:write:entry [3]
when (__pid == 400)[4]
{[5]
count++;
/* Print a message for every 20 system calls */
if (count % 20 == 0)
printf("Total read/writes so far: %d¥n", count);
/* Exit when we exceed 100 system calls */
if (count > 100)
exit();
} [6]
/* print some statistics at exit */
@@END
{
printf("Terminating probe after %d system calls.¥n", count);
}
上記の例で使用されている次の上付き文字は、Vue スクリプトのさまざまなエレメントを表します。
- コメント
- (オプション) 宣言セクション
- プローブ指定
- (オプション) 述部
- アクション・ブロックの開始
- アクション・ブロックの終了
この単純なスクリプトを開始するには、次のコマンドを実行します。 この例では出力例の一部が表示されています。
# probevue count.e
Total read/writes so far: 20
Total read/writes so far: 40
Total read/writes so far: 60
...
...
probevue コマンドを実行するには特権が必要です。 前述のコマンドを正常に実行するには、スーパーユーザーでログインするか、システムの任意のプロセスで実行されたシステム・コールをプローブする特権を持っている必要があります。