210 likes | 282 Views
OS カーネル用の アスペクト指向システム. 柳澤 佳里* 光来 健一* 千葉 滋* *東京工業大学 情報理工学研究科 数理・計算科学専攻. カーネルプロファイリング. 動機: ネットワーク性能の劣化を調査 ダウンロード中に SSH のレスポンスが悪化 十分なネットワーク帯域があるのに発生 カーネル内にボトルネック? 疑わしい場所は無数に存在. カーネルプロファイラが必要. プロファイル. pr_slowtimeo. tcp_slowtimeo. m_copydata. pr_output. tcp_output. ether_output.
E N D
OSカーネル用のアスペクト指向システム 柳澤 佳里* 光来 健一* 千葉 滋* *東京工業大学 情報理工学研究科 数理・計算科学専攻
カーネルプロファイリング • 動機: ネットワーク性能の劣化を調査 • ダウンロード中にSSHのレスポンスが悪化 • 十分なネットワーク帯域があるのに発生 • カーネル内にボトルネック? • 疑わしい場所は無数に存在 カーネルプロファイラが必要 プロファイル pr_slowtimeo tcp_slowtimeo m_copydata pr_output tcp_output ether_output tcp_usrreq sbappend ip_output copyin m_copy sosend if_output write socket TCP IP datalink
従来のカーネルプロファイリング技術 • 測定粒度が固定 • 関数単位 –μDyner [Marc ’03], TOSKANA [Michael ’05] • サポートされた種類のイベント –LKST [畑崎 ’03] • 任意の粒度で測定 • メモリ中のアドレスを直接指定 –KernInst [Ariel ’02] • 構造体、ローカル変数、インライン関数、static関数、マクロなどのアドレスが実行時に消失
プロファイルできない例 • 構造体メンバへの代入を逐一プロファイル • mbuf構造体 - ネットワークI/Oで多用 • アドレスの直指定はユーザに重荷 • 測定したい処理のアドレスを特定できない tcp_output(…) { struct mbuf *m; m->m_len = hdrlen; … } struct mbuf { struct m_hdr m_hdr; … } #define m_len m_hdr.m_len アドレス情報はバイナリに欠如
KLAS (Kernel Level Aspect-oriented System) • Source-based binary-level dynamic weaving • カーネル用アスペクト指向システム • ソースレベルで挿入コードと位置を指定 • アスペクトをXMLとして記述 • 動的にコード挿入 • 再コンパイル・再起動が不要 • 任意の処理を指定可能 • コンパイラの改造によりシンボル情報を拡張 • 実行時にweaverがシンボル情報を利用可能に
関数ポインタ呼び出し カーネル内のポリモルフィズム的コードで多用 E.g.) VFS、ファイル、ソケットなどの入出力 データアクセス まとまったデータのやり取りを行う箇所で多用 E.g.) mbuf、ファイルキャッシュの統計情報 KLASにより指定可能となる処理 fo_read(…) { return ((*fp->f_ops->fo_read(…)); } tcp_input(…) { … m->m_len += hdrlen; m->m_data -= hdrlen; …. }
KLASの文法 m_lenへのアクセスをポイントカットとして抽出 <aspect name=“log_reset_len”> <pointcut> <field-accessname=“m_len” structure=“mbuf” /> </pointcut> <advice-before> struct timespec ts; nanotime(&ts); printf(“%d,%lld”, ts.tv_sec, ts.tv_nsec); </advice-before> </aspect> ポイントカット位置で時間を表示
KLASの文法 m_lenへのアクセスをポイントカットとして抽出 <aspect name=“log_reset_len”> <pointcut> <field-access name=“m_len” structure=“mbuf” /> </pointcut> <advice-before> struct timespec ts; nanotime(&ts); printf(…); </advice-before> </aspect> tcp_output(…) { struct mbuf *m; struct timespec ts; ….. printf(…) m->m_len = hdrlen; … 挿入
実装の概要 OSソースコード アスペクト (XML) - 測定点 - 測定点で実行するコード KLAS_gcc KLAS アドレス リゾルバ シンボル 情報 シンボル情報抽出 アドバイス ローダ フック 挿入 コンパイル フック OSカーネル (FreeBSD) コンパイル済アドバイス
KLAS_gccの実装 • gccを改造 • 出力するシンボル情報を拡張 • 構造体メンバアクセスのファイル名、行を出力 ハッシュ表 ip_output(…) { struct mbuf *m0; … m0->m_pkthdr … } 1 2 KLAS_gcc • ハッシュ表に構造体名、IDを保存 • IDをキーにして構造体名を取得 • ファイル名、行番号、構造体名、メンバ名を出力 3 シンボル情報 /usr/…/ip_output.c:879:mbuf.m_pkthdr
アドレスリゾルバ:メンバアクセスとアドレスの対応アドレスリゾルバ:メンバアクセスとアドレスの対応 • 構造体名、メンバ名を渡すと対応するファイル名、行情報の一覧を得る • 拡張シンボル情報を検索 • ファイル名、行情報よりアドレスを得る • バイナリに入っているデバッグ情報を調査 拡張シンボル情報 debug_info 35 2 0 4 1 “ip_output.c” “GNU C Compiler” “frodo:/usr/src/sys/…” … … /usr/…put.c:175:ip.ip_v /usr/…put.c:176:ip.ip_hl … /usr/…257:mbuf.m_flags 構造体名 メンバ名 対応する ファイル名、行 アドレス
アドバイスローダ:アドバイスのカーネル内部へのロードアドバイスローダ:アドバイスのカーネル内部へのロード • カーネルモジュール(KM)としてロード • KMでは重複しない任意の関数をロード、使用可能 コンパイル #include <sys/types.h> #include <sys/module.h> … static int log_mbuf_loader(…) { … } int log_mbuf(….) { ヘッダ コンパイル済みアドバイス (カーネルモジュール) ロード(kldload) struct timespec ts; nanotime(&ts); printf(…ts.tv_nsec); アドバイス OSカーネル フッタ } DECLARE_MODULE(…ANY);
フック挿入:カーネルへのフック埋め込み • ブレークポイントトラップ(BPT)をフックに使用 • x86では1byte命令で実行フローを破壊しない • 動作 3.BPT挿入 BPT フック挿入 アドレスマップ コンパイル済みアドバイス 2.アドレスマップに登録 1.アドバイスのアドレスを取得
フック挿入:カーネルへのフック埋め込み • ブレークポイントトラップ(BPT)をフックに使用 • x86では1byte命令で実行フローを破壊しない • 動作 (フック作動時) BPT 1.処理が遷移 フック挿入 トラップ処理ルーチン アドレスマップ 3.アドバイスを実行 2.対応アドバイス の確認 コンパイル済みアドバイス
実験I:カーネルコンパイル時間 • 実験内容 • KLAS_gccのオーバーヘッドを測定 • KLAS_gcc、gccのカーネルコンパイル時間を比較 • 実験環境 • CPU: AMD Athlon 2200+, Mem: 1GB, HDD: UDMA133, gcc: 3.4.2 • 実験結果 約7%実行時間が増加 User: 約3%, System: 約38%
目的 フックの数と実行時間の変化を調査 実験内容 実験用システムコールの実行時間を測定 システムコール内で千個の関数を順に呼び出し 各関数に挿入するフックは高々1つ フックにより実行するコード内容は空 実験結果 実験II: フック数と実行時間 実験環境: FreeBSD 5.2.1 経過時間(s) フック数 フックの処理にDDBを利用した実装が原因 DDBはフック処理時に全BPTを消去、復帰
関連研究(1) • アスペクト指向システム • AspectC++ [Olaf ’02] • ソースレベルのアスペクト指向システム • 実行時のフック埋め込みは不可 • μDyner [Marc ’03] • 動的にフック埋め込みを実施 • コンパイル時にフック埋め込み可能箇所が決定 • ポイントカット可能位置の増加でコードサイズが増加 • TOSKANA [Michael ’05] • NetBSDカーネルに実装されたアスペクト指向システム • 関数の開始、終了位置にてフック埋め込みを実施 • 関数の粒度より細粒度のフック埋め込みは不可
従来のC/C++用アスペクト指向システム • 動的アスペクト指向システム • シンボル情報が少なくポイントカット指定が限定的 • 関数の先頭のみをポイントカットとして指定可能 • コンパイル時に構造体、マクロの情報が消失 • 静的アスペクト指向システム • ポイントカット、アドバイスの変更のたびに再コンパイル、再起動が必要 • 再起動によりメモリ内容が消失 • 再起動には長時間消費し開発効率が低下 KLASではシンボル情報を拡張し、実行時に構造体をポイントカット可能
関連研究(2) • カーネルプロファイラ • LKST [畑崎 ’03] • 決められたイベントの箇所でログ出力可能 • KLASは関数呼び出し、構造体アクセスでログ出力可能 • カーネルコード変換 • KernInst [Ariel ’02] • カーネル内の任意の箇所にコード挿入可能 • バイナリの情報のみ使用可能 • 挿入するコードの指定が機械語に近く、煩雑 • KLASはソースレベルの情報で指定可能
まとめ • カーネル用アスペクト指向システムKLASの提案 • FreeBSD、gccを改造して実装 • ソースコードを参照し、実行中のバイナリにフック埋め込み • コンパイラを改造し、シンボル情報を拡張 • 拡張したシンボル情報を用いてフック埋め込みアドレスを取得 • フックとしてBPTを使用 • 実験 • カーネルコンパイル時間が約7%増加することがわかった • フックの数に対して非線形に消費時間が増加することがわかった
今後の課題 • フックの処理時間の改善 • 実装の変更による所要オーダーの軽減 • 高速化のためにKerninstベースの開発を検討 • フック可能な処理を増加 • インライン関数、マクロに対応 • フックをより正確な位置に挿入 • コンパイラの改良により行よりも細かい単位でフック挿入 • 最適化により消える命令の取り扱いを検討