Systemtapを試してみる
AWS EC2インスタンスにSystemtapをインストールして軽く試してみたのでそのメモ。
インストール
- 参考
- SystemTap: getting started with dynamic EC2 instance diagnostics
上の通りに、kernel-devel, kernel-debuginfo, systemtap をインストールする。
以下のコマンドが成功すれば、インストール成功。
sudo stap -ve "probe vfs.read {printf("hello systemtap\n"); exit()}
-eオプションはコマンドラインにコードを記述する際に必要。Pythonの-cみたいなもの。
-vはおなじみのverbose。
ユーザをstapuser,stapdevグループに追加すると、sudoをつけなくても実行できますが、以下ではやっていません。
Getting Started
- 参考
基本文法
Systemtap はSystemtap専用のスクリプト(*.stp)を用いて、カーネル内の情報を集める。
基本的な文法はC言語+αな感じで、以下の通り。
global グローバル変数;
function hoge(引数){
// コード
}
probe イベント {
// 情報収集用コード
hoge(引数);
} // イベント発生時に実行される
probe イベント.return {
// 情報収集用コード
} // イベント終了時に実行される
実行後にSystemtapではカーネル内の動作をイベントとして捉えて、そのイベント発生時、または終了時(.returnをつける)に{}ブロックに記述されたコードを実行する。
複数のプローブで用いるコードを共通化するためにfunctionを使用することが出来る。
関数へのジャンプアドレスを書き換えてプローブに飛ばしてから、プローブの実行後に本来の関数に飛ばしてるのかな?
基本的な動作順序は次の通り。
IBM developerWorksに模式図があります。
- Pass1 : stpスクリプトをパースして解析木を作成
- Pass2 : カーネルのデバッグシンボルを使用してシンボルの名前を解決
- Pass3 : スクリプトをC言語ソースに変換
- Pass4 : 変換したC言語ソースをカーネルモジュールとしてビルド
- Pass5 : ビルドしたカーネルモジュールを実行
イベント
probeの後ろにくっつけるイベントには以下のようなものがある。
- begin : stpスクリプトの開始時に実行。
- end : stpスクリプトの開始時に実行。
- kernel.function("*") : カーネル内の関数の実行時に実行。例えば、functionの引数に"sys_sync"を指定すると、"sys_sync"実行時に実行される。また、ワイルドカードを使用できる。
- kernel.function("*") : こちらは関数の終了時に実行される。
- kernel.syscall.* : システムコールが発行されると実行される。例えば、syscall.openとするとopen()が呼ばれた時に実行される。
- kernel.function("*@kernel/fork.c:934") : C言語ソースを指定することもできる。左の例はkernel/fork.cの934行目にヒットする。
- module("ext4").function("*") : カーネルではなくモジュールを指定する場合はこちら。
- timer.ms(10) : 10msごとに実行。他に以下のような単位を使用可能。
- s : 秒
- us : マイクロ秒
- ns : ナノ秒
- hz : ヘルツ
- jiffies : jiffy
kernel.functionやmoduleの具体的なプローブポイントを調べるには以下のようにする。
sudo stap -L 'kernel.function{"*"}'
上で紹介した以外のプローブタイプは以下のコマンドで調べられる。
sudo stap --dump-probe-types
sudo stap --dump-probe-alias // よく使われるプローブ対象にはエイリアスがある
組み込み関数
T.B.D