os カーネル用 アスペクト指向システム klasy

34
1 OS カカカカカ カカカカカカカカカカカ KLASY カカ カカ カカ カ カカ カ カカ カ カカカカカカ カカカカカカカカ カカ カカカカカカ

Upload: luke

Post on 17-Jan-2016

104 views

Category:

Documents


1 download

DESCRIPTION

OS カーネル用 アスペクト指向システム KLASY. 柳澤 佳里 光来 健一 千葉 滋 石川 零 東京工業大学 情報理工学研究科 数理・計算科学専攻. プロファイリングコードを 実行中のカーネルに挿入するには?. 目的 : 任意の点でタイムスタンプをロギング 性能チューニングのため 例 ) パケット到達からカーネルバッファにいたるまでの経過時間を調査 既存の方法 カーネルプロファイラを利用 ? 決まった点でしかログを取得できない カーネルソースコードを変更し、再コンパイル ? 面倒くさくて、ミスしがち. プロファイリングコード. - PowerPoint PPT Presentation

TRANSCRIPT

1

OS カーネル用アスペクト指向システム KLASY

柳澤 佳里 光来 健一 千葉 滋 石川 零東京工業大学 情報理工学研究科 数理・計算科学専攻

2

プロファイリングコードを実行中のカーネルに挿入するには? 目的 : 任意の点でタイムスタンプをロギング

性能チューニングのため 例 ) パケット到達からカーネルバッファにいたる

までの経過時間を調査

既存の方法 カーネルプロファイラを利用 ?

決まった点でしかログを取得できない カーネルソースコードを変更し、再コンパイル ?

面倒くさくて、ミスしがち

3

プロファイリングコード

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

Linux カーネルソースコード (fs/attr.c)

struct timeval tv;do_gettimeofday(&tv) ;print_tv(tv);printk(“%ld”, inode->i_uid);

挿入プロファイリングコード

ソースコードの指定した行にて変数の値とタイムスタンプを記録

再コンパイル、再起動無しでプロファイリングしたい

4

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]);

Kerninst [Tamches et al. ’99]

実行時コード操作ツール アセンブリレベルの抽象度 開発者は次のアドレスの調査が必要 :

コードを挿入する機械語のアドレス 記録する変数が格納された場所のアドレス

void print_log() { … __asm__ (“movl %%ebp, %0” : “=r”(ebp)); uid = ((struct inode*)ebp[11])->i_uid; /* ebp[11] is inode */ …

サンプルコード : Kerninst を用いてログを取得

5

KLASY

Kernel-level Aspect-Oriented System ソースコードレベルの抽象度

アスペクト指向プログラミング (AOP) を用いた利点 KLASY により開発者は :

ソースコードレベルの視点で任意の実行点を選択可能 ポイントカット

C 言語でプロファイリングコードを記述可能 アドバイス

選択された点で実行されるコード 実行点で利用可能な変数にアクセス可能

6

ロギング

AOP のキラーアプリケーション ロギング (or プロファイリング ) コードは独立し

た別個のモジュールに分離 なぜ新しい AOP システムが必要か ?

既存の C 言語用動的 AOP システムの問題 実行時コンテキストの取得が不可能 : 変数アクセスがで

きない 構造体メンバーアクセスのポイントカットが不可能

たとえば、 inode->i_uid がアップデートされたときのタイムスタンプを調査不可能 プロファイリングに不可欠

7

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

8

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクトアドバイスボディで使うヘッダーファイルを指定

9

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

10

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

access(inode.i_uid) ポイントカットで

inode->i_uid を選択

11

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

within_function() により選択範囲を inode_change_ok 関数内に制

限。

12

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

実行時コンテキスト取得 :

inode_value に選択した構造体 (inode) への参

照を設定

13

KLASY のアスペクト例

<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(&amp;tv); print(i-&gt;i_uid, tv.tv_sec, tv.tv_usec); </before> </advice></aspect>

pointcut

advice

int inode_change_ok(…){ … if ((ia_valid & ATTR_UID) && … attr->ia_uid != inode->i_uid) … goto error;

if ((ia_valid & ATTR_GID) && …}

選択

Linux カーネルコード (fs/attr.c)アスペクト

タイムスタンプを取得し、 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 カーネ

ル本体フック

OS カーネル

アスペクトコンパイラー KLASYgcc

insmod

18

処理の流れ

コンパイル済みアドバイス

アスペクト OSソースコード

ポイントカット

拡張シンボル情報

ウィーバーOS カーネ

ル本体フック

OS カーネル

アスペクトコンパイラー KLASYgcc

insmod

19

KLASY gcc

KLASY gcc は次のシンボル情報を収集 : 構造体メンバーアクセスのあるファイル名、行

番号 コンパイラーのパーザーを拡張 従来の gcc ではこの情報は消失

各行の先頭命令のあるアドレス コンパイル時にデバッグオプション (-g) を利用 構造体メンバーアクセスのポイントカットにこれも必

20

処理の流れ

コンパイル済みアドバイス

アスペクト OSソースコード

ポイントカット

拡張シンボル情報

ウィーバーOS カーネ

ル本体フック

OS カーネル

アスペクトコンパイラー KLASYgcc

insmod

21

ウィーバー

Kerninst を用いポイントカットで選択した点にフック挿入

フック アドバイスボディを呼び出すためのコード

フック挿入アドレスの取得方法 構造体メンバーアクセス

ファイル名、行番号 行の先頭アドレス

拡張シンボル情報を利用

22

アンウィーブ

KLASY では実行時に OS カーネルから織り込んだアスペクトを削除可能 プロファイリングには重要な機能

一般に利用者は様々なアスペクトを試用 観察効果を避けるため不要なアスペクトの削除は必要

利用者はわかりやすい名前でアスペクトを指定可能

Kerninst を用いてウィーバーの入れたフックを消去

23

アスペクト例における実行時コンテキストの取得

<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(&amp;tv); print(i-&gt;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

Linux カーネルソースコード (fs/attr.c)アスペクト

ローカル変数を取得し、アドバイス内で利用

24

実行時コンテキストの取得の実装

ウィーバーと KLASY gcc の連携により実現 KLASY gcc にて構造体への参照方法を保存

ローカル変数から目的の構造体への参照に至る方法を保存 例 )

inode.length → &inodeinode_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-&gt;protocol != ETH_P_ARP) { STORE_DATA($pc$); STORE_DATA(skb); DO_RDTSC(timestamp); STORE_DATA(timestamp); } </before></advice></aspect>

ARP パケットを無視プログラムカウンタ、sk_buff 出現位置、タイムスタンプを保存

ワイルドカード

skb->protocol

27

トレース結果

プロセススケジューリングがボトルネックと判明 Skb_copy_datagram_iovec 関数はプロセスの発行し

たシステムコールから呼び出されるのでTime scale of packet arrival

0.1 1 10 100 1000Elapsed time

差が大きい

skb_copy_datagram_iovec

1000_clean_rx_irq

netif_receive_skbip_rcv

ip_rcv_finish tcp_v4_do_rcv

tcp_v4_rcv tcp_rcv_established

__kfree_skb

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 2.6.10

Kerninst 2.1.1, gcc 3.3.3, Intel Ethernet PRO/1000

32

実験結果

現実的なオーバーヘッドであることを確認 オーバーヘッド :

0 ~ 12 % 平均 : 4.4 %

dhry2reg: drystonesyscall: システムコールpipe: pipe システムコールexecl: execl システムコールcontext: コンテキストスイッチ

0200400600800

1000

dhry2

reg

sysc

allpip

eex

ecl

conte

xt

Linux KLASY

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 が有用であると確認 性能ボトルネックがプロセススケジューリングにあると

判明