カーネルモジュールとeBPFアプリを書いてみた
LinuxカーネルモジュールとeBPFアプリケーションを作ってみた。 とりあえずやってみたのは次のこと。
- カーネルモジュールの開発環境を準備する
- イベントフックを試してみる(カーネルモジュール, eBPF with bcc-python)
カーネルモジュールの開発環境を準備する
使った環境はこちら。ちょっと古い。
|
|
|
|
参考にしたのはこのブログと動かしながらゼロから学ぶLinuxカーネルの教科書の2つ。
イベントフック
ドキュメントにeBPFで対応してると書かれているイベントはCで12、Pythonで7。
- kprobe
- kretprobe
- tracepoint
- uprobe
- uretprobe
- USDT
- raw_tracepoint
eBPFのkprobeはカーネル内のjprobeっぽいフックポイントになっている。カーネルモジュールではkprobeは任意のアドレスをフックできる。一方でjprobe, kretprobeはkprobeで実装された高水準のフックポイントだ。 それぞれ関数のエントリポイント, 関数からのリターンをフックする。
uprobe, uretprobeはユーザープロセスのシンボルに対して使えるプローブになっている。
tracepointは事前にカーネルに組み込まれたフックポイント。同様にUSDTは事前にユーザープログラムに組み込まれたフックポイントになっている。
eBPFとは関係なく他にもイベントフックポイントはあるようだった。
- kprobe
- jprobe
- kretprobe
- uprobe
- hw_breakpoint
- Tracepoint
- USDT
jprobe(kprobe in eBPF)について
jprobe in カーネルモジュール
jprobeを使うためにすること。
- jprobeを使えるカーネル内のシンボルを確認する
- 対象の関数と同じスキーマのイベントハンドラを実装する
- jprobe構造体を定義する
register_jprobe(&jprobe_instance)
を呼び出してjprobe構造体をイベントハンドラとして登録するunregister_jprobe(&jprobe_instance)
を呼び出してイベントハンドラを解除する
|
|
jprobeを使うカーネルモジュールのサンプルは下のようになる。jprobe_return/0
の呼び出しが必要とのこと。
|
|
ref. https://gist.github.com/dzeban/a19c711d6b6b1d72e594
kprobe in eBPF
前に使ったサンプルコードに attach_kretprobe() の呼び出しを加えている。
eBPFの開発環境については下のパッケージインストールしました。
|
|
BPFインスタンスの attach_kprobe/2 メソッドを使い event のハンドラとして fn_name を登録して使います。
ここでBPFのハンドラが受け取る *ctx の中身はkprobeの場合は struct pt_regs が入っているらしい。
|
|
なんとなくサンプルコードを走らせたり入門的な記事を拾い読みして感じをつかんだと思う。
次は下を考えている。
- 公式資料やコミュニティへのリンクを集める
- bpfオブジェクトを自力でビルドして bpf(2) で利用したりubpf上で走らせるなどを試す
- 他のイベントをフックする
- 特にeBPF, XDPの実例に目を通したり使ってみる
- オライリーのLinuxデバイスドライバを読み通す
- デバイスファイルを提供するなどカーネルモジュールの実装練習
- カーネルモジュールやカーネルをQEMUでデバッグ
参考資料
- Linuxカーネルモジュール自作入門 kprobesでカーネル空間ブレークポイント
- kprobe - Linuxの備忘録とか・・・(目次へ)
- jprobe - Linuxの備忘録とか・・・(目次へ)
- kretprobe - Linuxの備忘録とか・・・(目次へ)
- hw_breakpoint - Linuxの備忘録とか・・・(目次へ)
- Linux Kernel: prink(print kernel)によるメッセージ出力
- 組み込みLinuxデバイスドライバの作り方 (1) - Qiita
- Linuxでデバイスドライバを作る - Qiita
- Linux Kernelの簡単なCharacter Deviceを作成する方法(Linked List APIの使用方法サンプル)
- ユーザランドからデバイスドライバを呼び出す - Linuxデバイスドライバ開発
- Linuxデバイスドライバ開発
- Linuxデバイスドライバ開発
- bccとUSDTを使ってMySQL/PostgreSQLのクエリログを取得する
- TCP Tracepoints
- Systemtapを支えるuprobeを直接いじってみる - Qiita
- hw_breakpoint - Linuxの備忘録とか・・・(目次へ)
- perf, ftraceのしくみ - 睡分不足
- バグ調査やパフォーマンス改善に役立つ!eBPFを用いたトレーシングについて | さくらのナレッジ
- eBPF の紹介 - Qiita