パン屑の轍

ボドゲとかプログラミングとかゲームとか

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

基本文法

SystemtapSystemtap専用のスクリプト(*.stp)を用いて、カーネル内の情報を集める。

基本的な文法はC言語+αな感じで、以下の通り。

global グローバル変数;

function hoge(引数){
    // コード
}

probe イベント {
    // 情報収集用コード
    hoge(引数);
} // イベント発生時に実行される

probe イベント.return {
    // 情報収集用コード
} // イベント終了時に実行される

実行後にSystemtapではカーネル内の動作をイベントとして捉えて、そのイベント発生時、または終了時(.returnをつける)に{}ブロックに記述されたコードを実行する。

複数のプローブで用いるコードを共通化するためにfunctionを使用することが出来る。

関数へのジャンプアドレスを書き換えてプローブに飛ばしてから、プローブの実行後に本来の関数に飛ばしてるのかな?

基本的な動作順序は次の通り。

IBM developerWorksに模式図があります。

  1. Pass1 : stpスクリプトをパースして解析木を作成
  2. Pass2 : カーネルデバッグシンボルを使用してシンボルの名前を解決
  3. Pass3 : スクリプトC言語ソースに変換
  4. Pass4 : 変換したC言語ソースをカーネルモジュールとしてビルド
  5. 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