🌐

eBPF - bpftraceチュートリアル 編

2022/03/09に公開

本記事は、eBPFにおける有名ツールの一つであるbpftraceのチュートリアルです。インストール等の手順についてはUbuntu 20.04をターゲットとしています。以下、関連記事をいくつか書いていますので、必要に応じて参照して下さい。

bpftrace概要

https://github.com/iovisor/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にまとめられています。

Probe types
[2]

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ファイルとして用意して利用することも可能です。

sleepers.bt
tracepoint:syscalls:sys_enter_nanosleep
{
  printf("%s is sleeping.\n", comm);
}
$ sudo bpftrace sleepers.bt

参考文献

https://www.brendangregg.com/ebpf.html#bpftrace

脚注
  1. domain-specific language ↩︎

  2. https://github.com/iovisor/bpftraceから抜粋 ↩︎

Discussion