Download presentation
Presentation is loading. Please wait.
1
OSカーネル用 アスペクト指向システム KLASY
柳澤 佳里 光来 健一 千葉 滋 石川 零 東京工業大学 情報理工学研究科 数理・計算科学専攻
2
プロファイリングコードを 実行中のカーネルに挿入するには?
目的: 任意の点でタイムスタンプをロギング 性能チューニングのため 例) パケット到達からカーネルバッファにいたるまでの経過時間を調査 既存の方法 カーネルプロファイラを利用? 決まった点でしかログを取得できない カーネルソースコードを変更し、再コンパイル? 面倒くさくて、ミスしがち
3
プロファイリングコード ソースコードの指定した行にて 変数の値とタイムスタンプを 記録 再コンパイル、再起動
Linux カーネルソースコード (fs/attr.c) int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } 無しでプロファイリングしたい プロファイリングコード 挿入 struct timeval tv; do_gettimeofday(&tv) ; print_tv(tv); printk(“%ld”, inode->i_uid);
4
Kerninst [Tamches et al. ’99]
実行時コード操作ツール アセンブリレベルの抽象度 開発者は次のアドレスの調査が必要: コードを挿入する機械語のアドレス 記録する変数が格納された場所のアドレス サンプルコード: Kerninst を用いてログを取得 kmgr.findModule(“kernel”, &kmod); kmod.findFuction(“inode_change_ok”, &ifunc); ifunc.findEntryPoint(&entries); kmgr.findModule(“profiler”, &kmod); kmod.findFunction(“print_log”, &pf); hook = kapi_call_expr(pf.getEntryAddr(), args); kmgr.insertSnippet(hook, entries[0]); void print_log() { … __asm__ (“movl %%ebp, %0” : “=r”(ebp)); uid = ((struct inode*)ebp[11])->i_uid; /* ebp[11] is inode */
5
KLASY Kernel-level Aspect-Oriented System ソースコードレベルの抽象度 KLASYにより開発者は:
アスペクト指向プログラミング(AOP)を用いた利点 KLASYにより開発者は: ソースコードレベルの視点で任意の実行点を選択可能 ポイントカット C言語でプロファイリングコードを記述可能 アドバイス 選択された点で実行されるコード 実行点で利用可能な変数にアクセス可能
6
ロギング AOPのキラーアプリケーション なぜ新しいAOPシステムが必要か?
ロギング(or プロファイリング)コードは独立した別個のモジュールに分離 なぜ新しいAOPシステムが必要か? 既存のC言語用動的AOPシステムの問題 実行時コンテキストの取得が不可能: 変数アクセスができない 構造体メンバーアクセスのポイントカットが不可能 たとえば、inode->i_uidがアップデートされたときのタイムスタンプを調査不可能 プロファイリングに不可欠
7
KLASYのアスペクト例 pointcut advice アスペクト Linux カーネルコード (fs/attr.c)
<aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice ポイントカットされるのはどこ?、inodeがNULLのときはどうする? 利用者は手動で選択するのか (河野先生)
8
KLASYのアスペクト例 アドバイスボディで使う ヘッダーファイルを指定 pointcut advice アスペクト
Linux カーネルコード (fs/attr.c) アドバイスボディで使う ヘッダーファイルを指定 <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice
9
KLASYのアスペクト例 pointcut advice アスペクト Linux カーネルコード (fs/attr.c)
<aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice
10
access(inode.i_uid) ポイントカットで inode->i_uid を選択
KLASYのアスペクト例 アスペクト Linux カーネルコード (fs/attr.c) <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice access(inode.i_uid) ポイントカットで inode->i_uid を選択
11
within_function() により選択範囲を inode_change_ok関数内に制限。
KLASYのアスペクト例 アスペクト Linux カーネルコード (fs/attr.c) <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice within_function() により選択範囲を inode_change_ok関数内に制限。
12
inode_valueに選択した構造体(inode)への参照を設定
KLASYのアスペクト例 アスペクト Linux カーネルコード (fs/attr.c) <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice 実行時コンテキスト取得: inode_valueに選択した構造体(inode)への参照を設定
13
タイムスタンプを取得し、i_uidの値とともに保存
KLASYのアスペクト例 アスペクト Linux カーネルコード (fs/attr.c) <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } pointcut 選択 advice タイムスタンプを取得し、i_uidの値とともに保存
14
KLASYの対応する 主なポイントカット、アドバイス
access 本研究で提案 構造体メンバーアクセスを選択 execution 関数実行を選択 アドバイス before 選択された点の前でプロファイリングコードを実行 after 選択された点の後でプロファイリングコードを実行
15
実行時コンテキストの取得に使う ポイントカット
ポイントカット記述子 target accessポイントカットで選択したメンバーを持つ構造体変数への参照を取得 local_var accessポイントカットで選択した箇所でローカル変数への参照を取得 argument executionポイントカットで選択した関数の引数への 参照を取得 ローカル変数がないときにローカル変数を取ろうとすると…(京都大学: 八木先生)
16
KLASYの実装 Source-based binary-level dynamic weaving GNU C コンパイラ(gcc)を拡張
生成した拡張シンボル情報を用い: 構造体メンバーへのアクセスをポイントカット可能 実行時コンテキスト(変数のアドレス)を取得可能 Kerninstをバックエンドに利用 動的織り込みを実現 C言語でアドバイスを記述 ソースレベルの視点で記述可能 XML風のタグで囲まれている
17
処理の流れ OSカーネル OS アスペクト ソースコード KLASY アスペクトコンパイラー gcc 拡張シンボル情報 ポイントカット
insmod ウィーバー OSカーネル コンパイル済み アドバイス OS カーネル 本体 フック
18
処理の流れ OSカーネル OS アスペクト ソースコード KLASY アスペクトコンパイラー gcc 拡張シンボル情報 ポイントカット
insmod ウィーバー OSカーネル コンパイル済み アドバイス OS カーネル 本体 フック
19
KLASY gcc KLASY gccは次のシンボル情報を収集: 構造体メンバーアクセスのあるファイル名、行番号
コンパイラーのパーザーを拡張 従来のgccではこの情報は消失 各行の先頭命令のあるアドレス コンパイル時にデバッグオプション(-g)を利用 構造体メンバーアクセスのポイントカットにこれも必要
20
処理の流れ OSカーネル OS アスペクト ソースコード KLASY アスペクトコンパイラー gcc 拡張シンボル情報 ポイントカット
insmod ウィーバー OSカーネル コンパイル済み アドバイス OS カーネル 本体 フック
21
ウィーバー Kerninstを用いポイントカットで選択した点に フック挿入 フック フック挿入アドレスの取得方法
アドバイスボディを呼び出すためのコード フック挿入アドレスの取得方法 構造体メンバーアクセス ファイル名、行番号 行の先頭アドレス 拡張シンボル情報を利用
22
アンウィーブ KLASYでは実行時にOSカーネルから織り込んだアスペクトを削除可能 プロファイリングには重要な機能
一般に利用者は様々なアスペクトを試用 観察効果を避けるため不要なアスペクトの削除は必要 利用者はわかりやすい名前でアスペクトを指定可能 Kerninstを用いてウィーバーの入れたフックを消去
23
アスペクト例における 実行時コンテキストの取得
Linux カーネルソースコード (fs/attr.c) <aspect> <import>linux/time.h</import> <advice><pointcut> access(inode.i_uid) AND within_function(inode_change_ok) AND target(inode_value) </pointcut> <before> struct inode *i = inode_value; struct timeval tv; do_gettimeofday(&tv); print(i->i_uid, tv.tv_sec, tv.tv_usec); </before> </advice> </aspect> int inode_change_ok(…) { … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error; if ((ia_valid & ATTR_GID) && } ポイントカット selected ローカル変数を取得し、 アドバイス内で利用 アドバイス
24
実行時コンテキストの取得の実装 ウィーバーとKLASY gccの連携により実現 ウィーバーにて参照を得るトランポリンコードを作成
ローカル変数から目的の構造体への参照に至る方法を保存 例) inode.length → &inode inode_ptr->length → inode_ptr ウィーバーにて参照を得るトランポリンコードを作成 ローカル変数の格納場所をデバッグ情報をから取得 Gccの作成したデバッグ情報を利用 保存された方法で構造体への参照を得、アドバイスに渡す
25
ケーススタディ: ネットワークI/Oサブシステムの調査
目的 過負荷におけるLinuxネットワークサブシステムの 性能ボトルネックを発見 Sk_buff構造体へのアクセスをトレース Sk_buff構造体はLinuxにてネットワークサブシステムでバッファとして利用 Sk_buffのトレースによりネットワークサブシステムの挙動を把握 KLASYの実行時コンテキスト取得機能を利用 個々のパケットを識別するため 無関係なパケットを無視するため
26
トレースに用いたアスペクト ワイルドカード <aspect><advice> <pointcut>
access(sk_buff.%) AND target(arg0) </pointcut> <before> struct sk_buff *skb = arg0; unsigned long timestamp; if (skb->protocol != ETH_P_ARP) { STORE_DATA($pc$); STORE_DATA(skb); DO_RDTSC(timestamp); STORE_DATA(timestamp); } </before> </advice></aspect> skb->protocol プログラムカウンタ、 sk_buff出現位置、 タイムスタンプを保存 ARPパケットを無視
27
トレース結果 プロセススケジューリングがボトルネックと判明
Skb_copy_datagram_iovec関数はプロセスの発行した システムコールから呼び出されるので 差が大きい __kfree_skb ip_rcv skb_copy_datagram_iovec netif_receive_skb tcp_v4_rcv tcp_rcv_established 1000_clean_rx_irq ip_rcv_finish tcp_v4_do_rcv
28
ケーススタディでの accessポイントカットの有用性
Sk_buff構造体の全メンバーをaccessポイントカット Linuxネットワークサブシステムの挙動を把握 もし、executionポイントカットでやるとしたら… ネットワークサブシステムについての詳細な知識が必要 過不足なく関数を選択するため 本ケーススタディでは76箇所(関数21個)にてログ取得 最適化禁止が必須 Inline関数への対応が必要 現実と大幅に異なる OSカーネルは通常最適化オプションつきでコンパイルされる 例) Linux カーネルは-Os最適化オプションでコンパイル 本ケーススタディではstatic inline関数6箇所にてログ取得
29
KLASYの有用性 (まとめ) 構造体メンバーアクセスをポイントカット 実行時コンテキストの取得
構造体メンバーアクセスは大規模Cプログラムで使用 関数間でのデータの受け渡しに利用 ポリモルフィズムの実現に利用 メンバーに関数へのポインターを保持 例) 仮想ファイルシステム(VFS)、仮想デバイスなど 例) OS kernel (FreeBSD, Linux), X window System 実行時コンテキストの取得 実行時コンテキストがあると… 詳細な調査が可能 必要なデータのみのログ出力が可能 ログ保存領域を節約
30
既存の C言語用動的アスペクト指向システム
TOSKANA [Engel ’05], DAC++ [Almajali ’05], TinyC2 [Zhang ’03],and Arachne [Douence ’05] 実行時コード操作 関数実行、呼び出しのみポイントカット可能 シンボル情報を不使用 TOSKANA-VM [Engel ’05] 仮想機械上でOSカーネルを実行 実際のハードウェア上のプロファイリングは不可能
31
実験 UnixBenchによるベンチマーク 実験環境 Linux: 通常gccでコンパイルしたカーネル
-fomit-frame-pointerオプションあり KLASY: KLASY gccでコンパイルしたカーネル 実行時コンテキスト取得のため、-fomit-frame-pointerオプション 使用不可 デバッグ情報の示す変数位置と実位置がずれるため ほぼ-fomit-frame-pointer禁止によるオーバーヘッドを測定 実験環境 CPU: AthlonXP™ 1800+, Mem: 1GB, Linux Kerninst 2.1.1, gcc 3.3.3, Intel Ethernet PRO/1000
32
実験結果 現実的なオーバーヘッドであることを確認 オーバーヘッド: 0 ~ 12 % 平均: 4.4 %
dhry2reg: drystone syscall: システムコール pipe: pipeシステムコール execl: execlシステムコール context: コンテキストスイッチ
33
関連研究 C言語用静的アスペクト指向システム カーネルプロファイラー 実行中のカーネルを変更可能 プロファイリングコードの変更に再起動が必要
例) AspectC [Coady ’01], AspectC++ [Spinczyk ’02] カーネルプロファイラー LKST、 DTrace [Cantrill ’04]、SystemTAP [Prasad ’05]、 LTT [Yaghmour ’00] カーネル内で発生したイベントについてログを取得するツール プロファイラー開発者の設定した箇所でのみプロファイリング可能
34
まとめ KLASY (Kernel-level Aspect-oriented System)を提案
Source-based binary-level dynamic weaving 構造体メンバーへのアクセスをポイントカットで選択可能 実行時コンテキストを取得可能 ネットワークI/OサブシステムのプロファイリングにKLASYが有用であると確認 性能ボトルネックがプロセススケジューリングにあると判明 図4のグラフの分析を教えてほしい 図4の分析にて、ブレークポイント、ジャンプの挿入数、割合は調べていないのか 必ずしも通るpathとは限らないからやってなかった(^^;やろうと思えば$pc$を記録し、Kerninstのログと比較すればできそう。
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.