プロセススケジューリング 状態監視ドライバ&サポートプログラム by Masaaki Kumagai kumagai@emura.mech.tohoku.ac.jp ========================================================================= 0:はじめに ========================================================================= 本ソフトウエアはLinuxカーネルにおいて, 現在実行中のプロセスが どのような順番でスケジューリング(CPU割り当て)され, あるプロセスが いつCPUで実行されていたかを監視するために開発されたものである. 本システムは, モジュールとしてカーネルに組み込み, 実際のスケジュー リングを監視・記録する部分と, その情報を読み出し, 加工するユーザ プロセスとからなる. 対応OSは Linux 2.0.x および 2.2.x であり, CPU には Pentium 以降を想定している. これはPentium以降で追加された命令を時間計測に 使用しているためである. ========================================================================= 1:含まれるプログラムと簡単な解説 ========================================================================= ・pprof_mod.o スケジューリングを監視するためにカーネルに組み込む モジュール. カーネルのバージョンに依存するため, カーネルに応じて構築する必要がある. ・pprofdump pprof_mod.o で記録された情報を一覧形式で画面に出力する. CPUを割り当てられた時間, CPUを占有していた時間等が 出力される. ・pproftop Linux についてくる 'top' コマンドのように, CPU の占有率を 一定時間ごとに出力する. topコマンドに比べて, より精密な 時間情報が得られる. ・pprofrec スケジューリング情報をファイルに記録する. ・pprecdump pprofrec で記録された情報をもとに pprofdump 形式の出力を 行う. ファイル先頭からの時間で表示範囲を指定, 特定プロセスの 周辺を表示するためのトリガ機能などがある. ・pprecps pprofrec で記録された情報を PostScript 形式によるグラフに 変換する. pprecdump のような時間処理のほか, プロセス名を キャプションに変換するなどの機能を持つ. ========================================================================= 2:構築方法 ========================================================================= 基本的に % make で構築は完了するはずである. 注意点としては, /usr/include/linux が 使用目的のカーネルバージョンのものとなっている必要がある. これは 一般に /usr/src/linux/include を指しているので /usr/src/linux が 正常であれば良い. 生成されるプログラムは上述の通りであるが, pprof_mod.o はカーネルバージョンに依存し, またマルチプロセサ用(SMP)か 否かによっても異なるため, 注意が必要である. 動作テストは一部 rootで行う. まず, アクセスのための特別ファイルを 作成する. これは mknod でおこなうが, # make mkdev で行うことができる. (削除は make rmdev) 次に, モジュールをインストールする. いままで, 開発元ではこれといった トラブルが発生したことがないが, 万が一が考えられるため, 試験はなるべく 被害が起きてもかまわない状態でおこなう(重要なパーティションを umount するなど). 手順は # insmod pprof_mod.o とする. つぎに, root もしくは 通常のユーザで, % ./pprofdump とする. ここで, 画面にプロセスのスケジュール状態が表示されれば (連続して表示される), 試験は完了である. モジュールの除去は # rmmod pprof_mod で行う. ========================================================================= 3:各種設定 ========================================================================= 設定は Makefile および pprof.h で行う. ・コンパイラの指定 (Makefile)  一般的に C/C++ コンパイラとして gcc が使用可能と思われるが, 環境によっては gccのかわりに egcs などの場合があると思われる. その場合, 「CC=gcc」のかわりに「CC=egcs」などと設定する. ・デバイスファイル (Makefile)  モジュールと他のプログラムとの通信を行うための特別ファイルの 名前を「DEVICE=」で指定する. 特に変更の必要はないと思われる. ・キャラクタデバイスメジャー番号 (Makefile)  この番号は pprof_mod.o を登録する際に重要となる番号であり, Linux 既存のドライバで使用しているものと重なってはならない. 設定するに当たって, /usr/src/linux/Documentation/devices.txt および, /proc/devices を参考にすると良い. 問題なく insmod できていれば, 当面は変更の必要はないであろう.  なお, 変更した場合は, いったん特別ファイルを消去する 必要がある. すなわち, make rmdev, make mkdev とする. ・SMP対応 (Makefile)  マルチプロセッサ(SMP)対応に構築したカーネルの場合, 「DEFSMP = -D__SMP__」を有効にする.  SMP 対応にコンパイルしたものをSMP非対応カーネルに insmod した場合はエラーが発生して組み込みができない. また SMP非対応にコンパイルしたものをSMPカーネルで 使用すると正常な記録はできない. ・CPU周波数 TSCPerMSEC(config.h)  本プログラムではPentium以降のCPUでサポートされている RDTSC という命令を使用している. これはCPUクロックごとに カウントアップする64ビットのカウンタの値を読むというもの である. この数値を実時間に変換するための定数がこれである. 実際には1ミリ秒あたりに何クロックあるかを指定する. おおよそCPUの公称クロック数でかまわないが, 調整することを 推奨する. 調整方法として簡単なのは % pprofdump | grep Timer Timer interrupt check at 0.000[msec] Timer interrupt check at 100.004[msec] Timer interrupt check at 200.002[msec] として, 表示される数値をもとに微調整することである. これは pprof_mod.o にはなんら影響しない. なお, この表示は, Linux のタイマ割り込み周期(通常100Hz)と pprof.h 内の TI_MARK_CYCLE によって決まり, すべてデフォルトであれば 1000[msec] 単位になるはずである. この例では割り込み周期が 1kHz であるため, 100[msec]になっている. (厳密には, 割り込み周期は指定したものとは微妙に異なるため, 正確な時間とは言えないが, 精度は十分とおもわれる) ・各種定数 (config.h) SCHED_PROF_SIZE: 記録するバッファサイズ TI_MARK_CYCLE: タイマ割り込みを記録する間隔 PPRTABLE, PROCNAME, PROCCONV, POSTSCRIPT: pprocrec, pprecdump, pprecps で使用するファイル名 以上, 変更する必要はほとんどないと思われる. 一度構築したあとで設定を変更する場合, 再度 make する. Makefile を 更新した場合には make clean を行った方が良い. ========================================================================= 4:各プログラムの解説 ========================================================================= 4.1 pprof_mod.o  スケジューリングを監視するためにカーネルに組み込むモジュールである. 特にオプション等は無い. 組み込みは root で #insmod pprof_mod.o カーネルからの取外しは #rmmod pprof_mod で行う. 以下のプログラムは, 同時に一つのみである. ------------------------------------------------------------------------- 4.2 pprofdump  プロセスの実行状況を時間を追って連続して出力するプログラムである. オプション等は無く, 停止は Control-C (その他適当なシグナル)による. 表示は   pprofdum( 3305) at CPU1 spent 1.373[msec] at 42.002 counter 397 プロセス名(最大8文字), プロセスID, 使用CPU番号, CPU使用時間および 時刻, スケジューリングにおける優先度数値である. プロセス名に "CPUidle" と表示された場合, CPUはアイドリング状態にある. また, 時々, Timer interrupt check at 1399.997[msec] というタイマ割り込みの時間を示す情報がふくまれる(デフォルトでは タイマ割り込み100回に1回) ------------------------------------------------------------------------- 4.3 pproftop  pprofdump では順に表示していただけであるが, これをプロセス毎に 時間を合計し, "top" と同じように CPU の占有率を算出するのが, この プログラムである. topにくらべてより高いな時間分解能が得られる. また, マルチプロセサの場合, 全体に占める比率が出力される. 表示は 2CPU: total cputime: 7929msec CPUidle( 0) spent 99.9476% CPU time (7924.370[msec]) scheduled 65times even counter: 65436.00 pproftop( 3330) spent 0.0279% CPU time ( 2.210[msec]) scheduled 42times even counter: 161.48 のようになされ, プロセス名, プロセスID, CPU占有率・時間, スケジュール回数, 優先度数値の平均である. ------------------------------------------------------------------------- 4.4 pprofrec  スケジューリング情報を直接出力せず, ファイルに記録する. 結果は "pprtable.tbl" に生の情報が, "procname.tbl" にプロセスIDとプロセス 名の対応関係が記録される. pprecdump, pprecps ではこのファイルを 利用する.  記録した上で詳細に検証するばあいに便利である. ------------------------------------------------------------------------- 4.5 pprecdump  pprofrec で記録された情報をもとに pprofdump 形式の出力を行う. ファイル先頭からの時間で表示範囲を指定, 特定プロセスの周辺を表示する ためのトリガ機能などがある.  オプションがいくつかあり, length=<時間> 出力する時間範囲を指定する. デフォルト200ms start=<時刻> 出力を開始する時刻をファイル先頭からで指定する. デフォルト0ms trigger= で指定したプロセスが実行された時刻を 表示の中心とするように start を自動設定する. ただし, start が同時に指定されてた場合, それ以降で のプロセスが見つかった 時刻になる. プロセス番号を数値で指定する 必要があるが, procname.tbl に一覧がある. デフォルト:なし toffset=<時間> trigger時刻に対して, 表示範囲を前後させる. デフォルト:0 -help 簡単なヘルプを表示 cpudelta0,cpudelta1 CPU毎の時間がずれていると思われる場合に 微調整を行う. となっている. ------------------------------------------------------------------------- 4.6 pprecps  pprofrec で記録された情報を PostScript 形式によるグラフに変換し, 可視化する. 出力がPostScript であるため, 確認は gs, gv を用いる. TeX に挿入する場合には事前に BoundingBox を設定する必要がある. 出力は固定ファイル pprof.ps に上書きされる.  オプションは length=<時間> start=<時刻> trigger= toffset=<時間> cpudelta0,cpudelta1,-help pprecdump 参照 width=<長さ> 指定された出力時間を幅何ミリメートルの図に するかを指定する. デフォルトで180mm(A4) mag=<拡大率> 全体的に図を拡大する. width と mag の組合わせで 字を大きくしたりできる. デフォルトは1 tsstart=<時刻> tstick=<間隔> pprecps では記録をもとに自動的にタイマ割り込みの タイミングを算出して, 縦の罫線を作成する. この位置・間隔を手動で設定するときに使用する オプション. 指定しなければ自動設定される. となっている.  本プログラムを使用するには procconv.tbl という変換テーブルを用意 しておく. 内容は1行毎に <プロセス名> <キャプション> という形にする. 記述された順に出力において下から配置される. プロセス名に '*','?' のワイルドカード文字を使用した場合, 該当するもの すべてを同じ行に出力するようになる. キャプションに空白を使用したい 場合は '~' をかわりに使用する. 最終行にはその他すべてのプロセスを 出力するために '*' をプロセス名として使う必要があることが多い. 例: idle CPU~idling X X~server kterm* kterm * misc なお, アイドリングを示す場合には "idel" をプロセス名に使用する.  使用のコツは, ある程度周期が長かったり単発だったりするプロセスを 追うには trigger を使用し場所を特定, それをもとに start を設定すると きれいな図が作成できる. あとは必要に応じて, 時間範囲を length で 設定し, width 等で図を整える. ========================================================================= 5:動作原理 =========================================================================  ここではプロセスの動作状況を記録する原理について簡単に触れる. Linux のスケジュールを行う中核部分は /usr/src/linux/kernel/sched.c にある schedule() 関数である. その関数の最初の処理として, run_task_queue(&tq_scheduler); が実行される. これはあらかじめ, tq_scheduler に実行したい処理を登録しておくと, ここで実行してくれる ものである. そこで, 現在実行中のプロセスの情報を記録する関数を 作成し, 登録することで, プロセスがCPUをOSに返した(奪われた)直後の 情報が得られる. 1度実行すると削除されるため, 再登録する. データの記録はリングバッファーを構成していて, 常に最新の SCHED_PROF_SIZE個のデータを保持するようになっており, これを 外部のプログラムから /dev/pprof 経由で読み出す. あとはそれぞれ目的に応じて加工する. 時刻の取得には Pentium 以降で使用可能な RDTSC という命令を利用する. これは CPU のリセットから現在までの CPUの内部クロックを数えている 64ビットのレジスタの値を読み出す命令であり, 常識の範囲で単調増加する. (400MHz で1000年以上). 最近のパソコンでは電磁波低減のために, スペクトル拡散したクロックを使用するものがあるが, この時, 当然 時間精度は若干低下する. ========================================================================= 6:エラーの傾向と対策 ========================================================================= ◯insmod したときに device is busy といったメッセージが表示され, 組み込みできない 使おうとしたデバイスのメジャー番号がすでに使われている 可能性が高いです. 3節を参考にデバイスメジャー番号を 変更してみてください. ◯プログラムを実行したときに (open device): No such file or directory といわれる. アクセス用の特殊ファイルがみつかっていません. root で make mkdev としてみてください. ◯プログラムを実行したときに Operation not supported by device と いわれる. ドライバが稼働していません. insmod pprof_mod はしてありますか? 正常に組み込まれていますか? /proc/devices に process profiler という行はありますか? ========================================================================= 7:使用上の注意 ========================================================================= ・本ソフトウエア群は作者が実験を行う上で必要なものとして開発したため, 当然, 動作テストをし, バグ等は使用に支障がないように除去してある. そのため, 危険性はそれほど高くはないと思われるが, カーネルに モジュールを挿入する以上, システムにダメージを与える危険性が 皆無ではない. なるべく, 万が一の自体にも影響の少ない状態で 実行することをお勧めする. ・本ソフトウエア群を使用したことによって, 発生したすべての損害に対して 作者 熊谷正朗 は一切の責任をおわないものとする. 利用者の責任の上 構築・利用をおこなって頂きたい. ・本ソフトウエア群の著作権は 作者 熊谷正朗 に属する. 改良・改造・再配布等に制限はつけないが, プログラムに問題があった 場合にはご連絡頂ければ幸いである. ・連絡先 kumagai@emura.mech.tohoku.ac.jp 熊谷正朗(まさあき)宛 所属 東北大学大学院工学研究科 機械電子工学専攻 江村研究室