述部
プローブ・ポイントの節の実行を条件付きで行う必要がある場合は、述部を使用できません。 述部セクションは、プローブ指定セクションの直後に when キーワードがあるかどうかによって識別されます。 述部自体は、通常の C 形式の条件式と括弧で構成されます。
述部セクション内の式には、いくつかの制限があります。
- カーネル・クラス変数は述部で許可されていません。
- 自動クラス変数は述部で許可されていません。
- 浮動小数点型変数は述部で許可されていません。
- Vue 関数は述部で許可されていません。
- 副次作用は述部で許可されていません。このため、= 代入演算子と += や |= のような複合代入演算子は許可されていません。
- 関数に渡される 9 番目以上のパラメーター (エントリー・クラス変数 __arg9 や __arg10 など) は述部で許可されていません。
if ... を使用すると、条項内の特定のアクションを条件付きで実行できます。 else ステートメントは、C の類似のステートメントと同様に機能します。 ただし、文節全体を条件付きで発行する場合は、代わりに述部を使用することをお勧めします。これは、 ProbeVue が述部の実行を最適化するように設計されているためです。
注: プローブ・ポイントが複数のプロセスに対して起動できる場合、述部内でスレッド・ローカル変数を使用することは、プローブを使用可能にすることによる全体的なパフォーマンスへの影響を軽減するための優れた方法です。 if 文を使用するよりも、述部で条件付き検査を使用する方が適切です。
以下のスクリプトでは、述部でスレッド・ローカル変数を使用して、特定の文字列が特定のファイルに書き込まれたときを効率的に検出します。 また、述部を使用して節のアクション・ブロック内で if 文を使用する例も示します。 ファイル名と文字列は両方とも、シェル定位置パラメーターを使用してパラメーターとしてスクリプトに渡されます。
/*
* Filename : chkfilewrite.e
*
* Capture when someone writes a particular word to a specific file
* takes 2 arguments: filename and word
*
* assumes file name is < 128
*
* Usage: probevue chkfilewrite.e \"<filename>\" \"<string>\"
*
* The backslashes above are necessary to prevent shell
* from stripping the double quotation mark.
*/
int open(char *fname, int m, int p);
int write(int fd, char *s, int size);
@@syscall:*:open:entry
{
__auto String fname[128];
fname = get_userstring(__arg1, -1);
if (fname == $1)
thread:opening = 1;
}
@@syscall:*:open:exit
when (thread:opening == 1)
{
thread:fd = __rv;
thread:opening = 0;
}
@@syscall:*:write:entry
when (thread:fd == __arg1)
{
__auto String buf[128];
if (__arg3 < 128)
buf = get_userstring(__arg2, __arg3);
else
buf = get_userstring(__arg2, 128);
if (strstr(buf, $2)) {
printf("%d wrote word to file.\n", __pid);
exit();
}
}
このプログラムを実行して「Error」の文字列が foo.log ファイルに書き込まれたときを検査するには、次のコマンドを実行できます。
probevue chkfilewrite.e \"foo.log\" \"Error\"
注: 上記のスクリプトを拡張するには、 close プローブを追加して、ファイルがいつ閉じられたかを検出します。これにより、元のファイルが閉じられ、新しいファイルが開かれて同じファイル記述子番号が再使用された後に、スクリプトが単語をキャッチしないようにすることができます。