カーネル挙動を追尾する「DTrace」の実力OS選択の新常識(4/8 ページ)

» 2005年04月22日 13時53分 公開
[大澤文孝,ITmedia]

 Solaris Dynamic Tracing Guideの「Chapter 21 syscall Provider」を読むと詳しく書かれているが、syscallプロバイダにおけるentryプローブでは、システムコールの引数がarg0、arg1、……、という変数に格納される。そして、returnプローブではシステムコールからの戻り値がarg0とarg1という変数に格納される仕組みを持つ。

 また、「man -s2 read」として、readシステムコールのmanを調べると分かるが、readシステムコールは、戻り値として読み込んだバイト数を返す。エラーがあった場合には負の数が戻るようになっている。つまり、arg0は、「読み取りが成功したらそのバイト数」、「読み取りが失敗したら負」が格納されることになる。

 リスト1では、「/arg0 > 0/」という条件を指定している。この条件は「読み取りが成功したら」という意味になるわけだ。また、読み取りが成功した場合には、次のように、sum関数の戻り値を変数@bytesに格納している。

@bytes[execname] = sum(arg0);


 sum関数は、その総和を求めるための関数だ。Dスクリプトでは、sum関数を始め、呼び出された回数を求めるcount関数、最小値を求めるmin関数、最大値を求めるmax関数などが用意されている。これらの関数を「集合関数」と言う(Solaris Dynamic Tracing Guideの「Chapter 9 Aggregations」を参照)。

 集合関数の戻り値は、先頭に「@」を付けた変数に代入する。ここでは@bytesという名前にしているが、変数名は任意で構わない。

 「@」を付けた変数は、「@変数名[キー]」のように表記して、指定のキーごとに値を格納できる。Perlを知っている人は、連想配列(ハッシュ)のようなものと考えると分かりやすいだろう。Dスクリプトでは、キーは、「@変数名[キー, キー, …]」のように多次元もできる。

 リスト1では「@bytes[execname]」として、execnameというキーで分類している。なお、execnameは、実行ファイル名を保持しているビルドイン変数である。そのため、実行ファイル名ごとに分けて集計される。

 ビルドイン変数には、このほかにも、プロセスIDを保持するpid、ユーザーIDを保持するuidなども用意されている(Solaris Dynamic Tracing Guideの「Chapter 3 Variables」を参照)。

  • dtrace:::END

 dtrace:::ENDは、Dスクリプトが終了する時にイベントが発生するプローブだ。リスト1ではprinta関数を用いており、集計しておいた@bytesの値を出力している。これにより、先の実行例に示したように、「Ctrl」+「C」キーを押してdtraceコマンドを終了させた場合にそれぞれの実行ファイルが読み込んだバイト数が表示されるというわけだ。

 printa関数は、集計関数の結果を出力する関数だが、単一値を出力する関数としてprintf関数も用意されている。またリスト1では用いてないが、printf関数やprinta関数では、C言語と同様に、「%d」「%s」といった書式指定子を使って、書式化出力することもできる(Solaris Dynamic Tracing Guideの「Chapter 12 Output Formatting」を参照)。

 なおdtraceモジュールにはSTARTというプローブ(dtrace:::START)も用意されている。STARTプローブは、Dスクリプトが実行されるとすぐに発生するものだ。例えば、何か変数を初期化したいような場面では、STARTプローブに処理を記述すればよい。

処理に要する時間を計測する

 さてシステムのパフォーマンスを計測するという目的を考えれば、ファイルを読み込んだ総バイト数ではなく、読み取りに要した時間を計測したいだろう。そのような場合には、システム関数への突入時から退出時までの時間差を計測して集計すればよい。スクリプト例は、次ページリスト2のようになる。

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ