eBPF - bpftraceチュートリアル 編
本記事は、eBPFにおける有名ツールの一つであるbpftrace
のチュートリアルです。インストール等の手順についてはUbuntu 20.04
をターゲットとしています。以下、関連記事をいくつか書いていますので、必要に応じて参照して下さい。
- eBPF - 入門概要 編
- eBPF - 仮想マシン 編
- eBPF - BCCチュートリアル 編
- eBPF - bpftraceチュートリアル編(本記事)
- eBPF - XDP概要 編
bpftrace概要
BCC同様、bpftrace
(SystemTapの後継)はIO Visor
が開発管理しています。
BCCのように一般的にeBPFを利用する場合には、eBPF本体のプログラムとトレーシング用のフロントエンドのユーザランド側の2つのプログラムを用意する必要があります。しかし、bpftraceでは独自のスクリプト言語 (DSL[1]) とコマンドラインツールを提供することで、カーネルサイドとユーザサイドを意識することなくより簡単に一つのプログラムでトレーシング処理を記述することが可能です。
内部的にはLLVMおよびBCCを利用してeBPFのバイトコードを生成し、ライブラリはlibbcc
を利用しています。
使い方としては、以下の例のようにbpftrace
コマンドを利用し、そのオプション引数で対象のDSLのソースコードを指定します。直接引数としてソースコードを書くこともできれば、別ファイルに書いたものを読み込むことも出来ます。
$ sudo bpftrace -e 'BEGIN { printf("Hello, World!\n"); exit(); }'
Attaching 1 probe...
Hello, World!
プローブ可能な種類
bpftraceは開発中と言ってもかなりの情報をトレース出来そうです。バスサイクルなどのハードウェア関連の情報からシステムコールの情報まで、プローブ一覧を表示してみたら6.9万種類ほどありました…(大多数はKprobeのカーネル関連)。詳細はReference Guideにまとめられています。
BCCとbpftraceの使い分け
まず押さえておく点として、BCCとbpftraceの違いに以下の2点があります。
- サポート言語
- ツールとしての安定性
BCCとbpftraceの一番の違いは、サポートしている言語です。BCCはPython, C++, luaです。一方、bpftraceは独自のDSL
のみです。
また、bpftraceは2022年3月時点でv0.14.1
でまだ開発中という状況です。
好みもあるかと思いますが、製品向けだったりガッツリとしたプログラムを書く時はBCC、ちょっとしたデバッグや観測、ちょっとしたスクリプト/ツールを作るときはbpftraceという感じになるかなと感じました。
インストール
$ sudo apt install bpftrace
インストールについては、公式マニュアルでターゲットOS毎にまとめられています。
サンプル(使い方)
プローブ可能な一覧を表示
$ sudo bpftrace -l
$ sudo bpftrace -l 'tracepoint:syscalls:sys_enter_*'
プロセス毎のシステムコールの発行回数を観測
$ sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'
Attaching 1 probe...
^C
@[gvfs-afc-volume]: 3
@[rtkit-daemon]: 4
(snip)
@[firefox]: 225
@[Xorg]: 405
@[gnome-shell]: 411
@[alsa-sink-HDMI ]: 8715
@[monit]: 10656
別ファイルのソースコードを利用
bpftrace用のソースコードはbt
ファイルとして用意して利用することも可能です。
tracepoint:syscalls:sys_enter_nanosleep
{
printf("%s is sleeping.\n", comm);
}
$ sudo bpftrace sleepers.bt
参考文献
-
domain-specific language ↩︎
Discussion