Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
PEPABO SUMMER INTERN VERSION 近藤うちお / GMO Pepabo, Inc. 2020.09.08 bcc Python Developer Tutorial 徹 底 解 説 !
Slide 2
Slide 2 text
この資料は何 •Python版「bcc Python Developer Tutorial」を通しでやってみる 際に参考になるかもしれない解説スライドです •@udzura の独断と偏見が含まれます •@udzura はRuby版BCCポート(*)を開発した人で、TutorialもRuby に移植した経験がありますが、それでも間違ったことを言っている可 能性はあります。 IUUQTHJUIVCDPNVE[VSBSCCDD
Slide 3
Slide 3 text
全体の攻略方針 •三分割できる •Lesson 1〜6: 第一章 BCCプログラミングの基本 •Lesson 7〜11: 第二章 収集したデータの出力方法 •Lesson 12〜16: 第三章 様々なるProbe •とにかく第一章が重要で難しい。 •ここさえ乗り切れば後はAPIを覚えていくフェーズになる。 •インターンの半分でLesson 6までやり切れば、ツールは何とか作れるはず?
Slide 4
Slide 4 text
環境について •Ubuntu Bionic で大丈夫 •カーネル 5.3 あたりを明示的に入れたければどうぞ。 その場合、linux-libc-dev パッケージを先のバージョンから ダウンロードして入れても良いかも。 •Focal はなんか不安定な印象がまだあるが、挑戦はいいんでは •Vagrant を使えば十分、むしろコンテナでは如何ともし難い •Linux の人も、いちおうVMを挟んでおきましょう
Slide 5
Slide 5 text
第一章 BCCプログラミングの基本
Slide 6
Slide 6 text
1. Hello World
Slide 7
Slide 7 text
BCCの動作確認 •やってることは: clone(2) のトレース •clone(2) は要するにfork()で、プロセスを作ったら呼ばれるsyscall •fork() -> exec() -> exit() の流れを復習しよう
Slide 8
Slide 8 text
2. sys_sync()
Slide 9
Slide 9 text
対象システムコールの変更 •kprobe__sys_BAR(...) という関数名をBCCで定義すると、 自動でkprobeにアタッチされる。 •sys_BAR kprobe はシステムコール BAR(2) に対応する ※ hello_world.py を改修する ※kprobe = カーネルのシンボルに紐づくフック
Slide 10
Slide 10 text
3. hello_fields.py
Slide 11
Slide 11 text
プログラムの基本形を覚える ※ printk() したら msg で取れる
Slide 12
Slide 12 text
4. sync_timing.py
Slide 13
Slide 13 text
BPF Mapの基本的な使い方
Slide 14
Slide 14 text
BPF Mapの基本的な使い方
Slide 15
Slide 15 text
BPF Mapの基本的な使い方
Slide 16
Slide 16 text
5. sync_count.py
Slide 17
Slide 17 text
前のコードを改修しよう • ヒントなど: • key に 0 以外を指定すればストアする 値を増やせるよ(不要か?) • lookup()してNULLなら初期値、 そうでなければ +1 した値を保存すれ ばカウンターになるのでは? • もう差を取る必要は実はない • outputの手段は今のとこprintk()しか ありませんね...
Slide 18
Slide 18 text
6. disksnoop.py
Slide 19
Slide 19 text
ブロックデバイスI/Oのトレース例 •押さえるべきこと: •trace_start()からtrace_completion()までの差分を計測している •struct request * のアドレスをキーがわりにする •一回一回のリクエスト構造体はカーネルのメモリ上では別々の位置 にあるはず(アドレスの使い回しはあるが、同時にはない) •printk() で無理やり3つの値を送っている
Slide 20
Slide 20 text
自力でゆっくり 読んでみましょう
Slide 21
Slide 21 text
第二章 収集したデータの出力方法
Slide 22
Slide 22 text
7. hello_perf_output.py
Slide 23
Slide 23 text
Perf buffer の使い方 •コツ: •trace_fields() 系はtracefsの一つのファイルをtailしてるだけで、 複数同時にアウトプットできなくて混ざる •Perf bufferにデータを送り込む専用のデータ構造 BPF_PERF_OUTPUT() •open_perf_buffer() はデータが来たときのコールバックの登録 •perf_buffer_poll() で待つ
Slide 24
Slide 24 text
8. sync_perf_output.py
Slide 25
Slide 25 text
4. の書き換え。 •コツ: •7. のコード構造を頭に叩き込んで落ち着いて頑張る。
Slide 26
Slide 26 text
9. bitehist.py
Slide 27
Slide 27 text
ヒストグラムの出し方 •コツ: •ヒストグラム専用のデータ構造とヘルパーがあって便利ですね •struct request のメンバの確認の仕方などを押さえとくといい
Slide 28
Slide 28 text
10. disklatency.py
Slide 29
Slide 29 text
disksnoop.py のリライト •コツ: •レイテンシ計測のパターンを思い出す •あとはレイテンシをヒストグラムに登録するだけ
Slide 30
Slide 30 text
11. vfsreadlat.py
Slide 31
Slide 31 text
定期表示系のトレーサの実装 •コツ: •CとPythonのファイル分割、b["dist"].clear() の2つの方法を 覚えるためのレッスン。 •他は新しいことはないので復習。
Slide 32
Slide 32 text
第三章 様々なるProbe、そして伝説へ...
Slide 33
Slide 33 text
12. urandomread.py
Slide 34
Slide 34 text
tracepoint の利用 •コツ: •普通にtracepointを使う場合専用のマクロがある •マクロ経由の場合明示的なアタッチは不要 •tracepoint のフォーマット確認の仕方を押さえる
Slide 35
Slide 35 text
ちなみに •@udzura が雑に書いたtracepoint補完確認コマンドがある。 • https://gist.github.com/udzura/6d40a3f010aff2a4a58f632627ab7f89
Slide 36
Slide 36 text
13. disksnoop.py fixed
Slide 37
Slide 37 text
kprobe → tracepoint の書き換え •コツというか...: •trepo() を使って当該tracepointの確認を... •してもよくわからんとなった場合は、 @udzura のRuby実装を眺め てもいいと思います。 •トレースポイント、ドキュメントがないよね...。
Slide 38
Slide 38 text
14. strlen_count.py
Slide 39
Slide 39 text
uprobe の利用 •コツ: •地味に初めて「文字列をキーとしたハッシュ」を扱うので注意 •その他は既存のProbeと扱いは変わらない •get_table() で取れるテーブルはdict風のインタフェースがある
Slide 40
Slide 40 text
uprobe の確認方法 •1) readelf -s •2) bpftrace (ただし、snap版は使えない)
Slide 41
Slide 41 text
15. nodejs_http_server.py
Slide 42
Slide 42 text
USDTの利用... •コツというか...: •node.jsをUSDT有効で用意するのが大変。頑張って •ヒント: “同じディレクトリにあるnode.jsのサーバプログラムを、 USDTを有効にした(--enable-dtrace)ビルドのnode.jsバイナリ で実行して計測する必要があります” •nodebrew はビルドオプションを渡せる。もしくは自分でbuild •USDT有効になっても、さらにusdt系の関数は癖があって大変。
Slide 43
Slide 43 text
USDTの確認方法 •1) readelf -n
Slide 44
Slide 44 text
USDTの確認方法 •2) bpftrace
Slide 45
Slide 45 text
16. task_switch.c
Slide 46
Slide 46 text
ここまでの総集編 •コツというか...: •finish_task_switch() の定義をちゃんとカーネルソースコードを見て 確認するといいと思う •eBPF C側の関数の第2引数以降は、元の関数の引数がスライドする •後は、今までの知識で!
Slide 47
Slide 47 text
17. Further Study
Slide 48
Slide 48 text
登り始めた ばかりだからな...(AA略)