第688回の
BCCのインストールとドキュメント
第688回も紹介したように,
eBPF自体はカーネルの仕組みであり,
$ sudo apt instal bpfcc-tools
実際にコンパイルを行うのはPythonライブラリ側です。よって
ちなみにBCCを使ってeBPFのプログラムを書くだけであれば,
BCC向けのコードを書く場合,
BCCではC言語でカーネル内部のロジックとデータの処理を実装し,
- BPF C:C言語部分のリファレンス
- BCC Python:Python部分のリファレンス
kprobeで特定の関数呼び出し時の処理を追加する
まずはBCCのサンプルにあるhello_
」clone(2)
」Hello, World!
」
from bcc import BPF
BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print()
ちなみにBCCのサンプルはPython 2を想定して書かれたスクリプトが多いようです。よってそのまま実行権限を与えても,/usr/
が)
さてまずはPython部分を説明します。BCC Pythonでは,
BPFの場合はインスタンス作成時のtext
」src_
」cflags="文字列"
」debug=数字
」
今回はtext
を使って直接次のようなC言語のコードを指定しています。
int kprobe__sys_clone(void *ctx)
{
bpf_trace_printk("Hello, World!\\n");
return 0;
}
まずは関数名のkprobe__
」イベント名__関数名
」
今回だとkprobe__
」sys_
」struct pt_
」void *
」
関数の中ではカーネルのAPIやBCCのAPIを呼び出せます。bpf_
はBCC側のAPIで,/sys/
に指定した文字列を出力します。ただし引数は最大3個とか,%s
」BPF_
などを使うことになるのでしょう。
これでC言語の部分の説明は完了です。最後に残ったのはBPF().trace_
」trace_
」bpf_
でtrace_
に出力されたデータを読み込んで表示するだけの関数です。
実際にこのコードを実行してみましょう。
$ sudo python3 hello_world.py (BCCによるコンパイルログ) b' tmux: server-5480 [001] d... 626046.065863: bpf_trace_printk: Hello, World!' b'' b' tmux: server-5480 [001] d... 626046.071380: bpf_trace_printk: Hello, World!' b''
バックグラウドで何かプログラムが動くたびにHello, World!
」
TASK PID CPU FLAG TIMESTAMP FUNCTION b' tmux: server-5480 [001] d... 626046.065863: bpf_trace_printk: Hello, World!'
追加でタスク名を表示してみる
たとえばタスクの名前を,
from bcc import BPF
bpf_text="""
#include <linux/sched.h>
int kprobe__sys_clone(void *ctx)
{
char comm[TASK_COMM_LEN];
bpf_get_current_comm(&comm, sizeof(comm));
bpf_trace_printk("Hello, World!: %s\\n", comm);
return 0;
}
"""
BPF(text=bpf_text).trace_print()
今回はbpf_
としてC言語部分をヒアドキュメント化してみました。長めのコードを書くなら,
bpf_
はカレントタスクのプログラム名を文字列にコピーしてくれるBCCのAPIです。あとは%s
」trace_
にはタスク名が表示されるため,
このようにeBPFのC言語部分は,