# kprobe
## 定義
kprobe(kernel probe)は、Linux カーネルの関数・命令を動的にインストルメンテーションするためのイベントソースである。2004年の Linux 2.6.9 で使えるようになった。標準的な実装は、実行中のカーネルコードの命令テキストを書き換えて必要な命令を挿入する方式で、関数実行開始のトレースでは既存の Ftrace 関数トレーシングを流用してオーバーヘッドを下げる最適化が使える。トレーサーが kprobe を使うと kprobe イベントが作られ、デフォルトではカーネルコードは無変更のまま実行される。関数からのリターンと戻り値は、trampoline 関数を挿入する kretprobe でトレースする。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 4 可観測性ツール]])
### perf(1) での実務操作(13章)
[[perf]](1) は kprobe を「プローブイベント(probe event)」として扱い、`perf probe --add <func>` で作成、`--del` で削除する。生成された `probe:<func>` イベントは perf list 上では他の静的イベントと区別なく Tracepoint event と表示される(初期化前はリストに現れない)。`%return` を付ければ kretprobe を作成できる。引数の取得方法は4通りに整理される。(1) カーネル debuginfo があれば `perf probe --vars <func>` で変数リストを直接取得、(2) debuginfo がない本番環境では、同一ハードウェア・カーネルの参照システムに debuginfo を入れ `-nv`(ドライラン・詳細出力)でレジスタ割り当てを調べてから対象システムでそのレジスタを指定、(3) プロセッサ ABI の知識から直接レジスタを特定、(4) BTF(BPF type format)という debuginfo 代替ソースを使う。リターン値は kretprobe の特殊変数 `$retval` で読める。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]] §13.7.1, §13.7.1.1)
### Ftrace tracefs での実務操作(14章)
perf(1) の「プローブイベント」抽象化より低レイヤーで、[[Ftrace]] は kprobe を tracefs 上のテキストインターフェースで直接操作する。`kprobe_events` ファイルへ `p:[GRP/]EVENT SYM[+offs] [FETCHARGS]`(プローブ設定)・`r[MAXACTIVE][:[GRP/]EVENT] SYM [FETCHARGS]`(リターンプローブ)・`-:[GRP/]EVENT`(クリア)という構文を echo で追加/削除する。作成された kprobe は `events/kprobes/<name>/` 配下にトレースポイントと同じ `enable`・`filter`・`trigger`・`format` を持つディレクトリとして現れ、トレースポイントと全く同じインターフェースで扱える。引数取得は Linux 4.20 以降 `$arg1`・`$arg2` などのエイリアス、それ以前はレジスタ名(x86_64 なら `%di`・`%si` など AMD64 ABI 準拠)を直接指定する。戻り値は kretprobe 配下の特殊変数 `$retval` で取得する。有効化された kprobe のヒット数・ミスヒット数は `kprobe_profile` ファイルに集計され、関数プロファイラでは重すぎる高頻度関数の監視に使える。BCC は最近のカーネルでは `kprobe_events` ではなく `perf_event_open(2)` ベースのインターフェースを使うため、BCC が有効化した kprobe は `kprobe_events` に現れない。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 14 Ftrace]] §14.6〜§14.6.5)
## 横断的知見
- **「プローブイベント」という呼称は、kprobe/uprobe/USDT を実装の違いを超えて統一的に扱う perf(1) の設計思想を表す**: 4章がkprobe を「トレースポイントを流用したイベントソース」として単体で説明するのに対し、13章は perf(1) がこれを uprobe・USDT と並べて「動的であり初期化が必要」という共通の性質でグルーピングし、初期化後は同じ Tracepoint event 表記で見せることを明らかにした。これは実装(カーネル命令書き換え vs ユーザー空間書き換え vs 静的メタデータ)が違っても、ツール利用者から見た抽象化を揃えるという設計判断であり、[[動的計装]]全般に見られる「無効時ゼロコスト・使用時のみ有効化」という原則の perf(1) における具体化である。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 4 可観測性ツール]], [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]] §13.7)
- **debuginfo がない本番環境での引数取得は、参照システムを介した間接的な手順として確立している**: 4章はkprobe のオーバーヘッド実測値(kprobe 最小76ns、kretprobe 最小212ns)を報告するにとどまるが、13章は同じ環境が debuginfo を持たない場合でも、同一ハードウェア/カーネルの別システムで一度レジスタ位置を調べてから対象システムへレジスタ指定を持ち込むという再現可能な回避策を具体的な手順として示す。オーバーヘッドの低さ(4章)と本番での運用可能性(13章)が組み合わさって、kprobe が「安価だが使いにくい」ではなく実務投入可能なツールになっていることが分かる。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 4 可観測性ツール]], [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]] §13.7.1.1)
- **perf(1) の「プローブイベント」は Ftrace の kprobe_events テキストインターフェースを上位から抽象化したものである**: 13章は perf probe による高水準操作を示すが、14章は同じ kprobe 機構を tracefs の `kprobe_events`・`events/kprobes/.../{enable,filter,trigger,format}` へ直接 echo することで操作する、より低レイヤーの姿を示す。両者は同一のカーネル機構(kprobe_events)を異なる抽象度のフロントエンドから叩いており、トレースポイントと同じ `events` ディレクトリ構造・フィルタ/トリガー構文を共有する点で kprobe が「独立した機能」ではなく tracefs のイベントソースのひとつとして統合されていることが分かる。引数エイリアス(`$arg1`/`$retval`)の構文は perf(1) にも流用されており、フロントエンド間で計装記法が共有されている。(Source: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]] §13.7.1, [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 14 Ftrace]] §14.6)
## 未解決の問い
- kprobe はカーネル関数・引数を公開する不安定 API とされるが、Ftrace 関数トレーシングを流用した最適化はどの範囲のカーネル関数に適用され、どこまでオーバーヘッドを下げられるか。
- kprobe(最小 76ns)と kretprobe(最小 212ns)のオーバーヘッド差はトランポリン関数のコストに起因するとされるが、この差はカーネルバージョンやアーキテクチャでどの程度変動するか。
- トレースポイント(安定API・約1,800種)と kprobe(不安定API・5万種以上)のカバレッジの差は、実務のトレーシングツール開発でどのような選択基準を生むか。
- BTF(BPF type format)が debuginfo の代替として標準化された場合、13章が示す「参照システムでレジスタを調べる」回避策はどこまで不要になるか。
- Ftrace の `kprobe_events` テキストインターフェースと perf(1) の `perf probe` はどちらもカーネル kprobe 機構を操作するが、両方を同時に(あるいは BCC の perf_event_open(2) 経由も含め3系統で)同一関数に使った場合、フィルタ・トリガーの競合や二重計装は起きないか。
## 関連
- 概念: [[uprobe]] / [[動的計装]] / [[eBPF]]
- エンティティ: [[Brendan Gregg]] / [[BCC]] / [[bpftrace]] / [[perf]] / [[Ftrace]] / [[trace-cmd]]
- ソース: [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 4 可観測性ツール]] / [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]] / [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 14 Ftrace]]
## 出典
- [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 4 可観測性ツール]](kprobe/kretprobeの仕組み、トレースポイントとの比較表、オーバーヘッド実測値)
- [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 13 perf]](§13.7.1 perf probe によるkprobe作成/削除、§13.7.1.1 引数取得の4手法)
- [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 14 Ftrace]](§14.6 kprobe_eventsテキストインターフェース、引数エイリアス、kprobe_profile)