ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

eBPFくじ引き

eBPFのヘルパー関数には bpf_get_prandom_u32() というものがあります:

Chromeの「この箇所へのリンク」を使いました)

bpf-helpers(7) - Linux manual page

これは色々な用途に使える(まず想像するのはサンプリングとか?)と思いますが、おみくじに使ってみました。

拙作 RbBCC で、 BCC + Ruby の例です。Python他でも似たようなコードは書けるでしょう:

#!/usr/bin/env ruby                                                                                                                                                         
require 'rbbcc'

b = RbBCC::BCC.new text: <<CODE
BPF_HASH(lottery, int, int, 1);                                                                                                                                             
                                                                                                                                                                            
int kprobe__sys_sync(void *ctx) {                                                                                                                                           
  bpf_trace_printk("Drawn\\n");                                                                                                                                             
  int key = 0;                                                                                                                                                              
  int got = bpf_get_prandom_u32() % 30 + 1;                                                                                                                                 
  lottery.update(&key, &got);                                                                                                                                               
  return 0;                                                                                                                                                                 
}                                                                                                                                                                           
CODE

t = Thread.new do
  sleep 0.5
  system "sync"
end
at_exit { t.join }

loop do
  table = b.get_table('lottery', leaftype: 'int')
  if (got = table[0]) && got.to_bcc_value.nonzero?
    puts "Winner: #{got.to_bcc_value}"
    exit 0
  end
end
  • 環境: 22.04.1-Ubuntu 5.19.0-46-generic

内容的には sync(2) をtraceして、かつ、プログラムの中で裏で sync コマンドを発行して引っ掛けてくじを引いていますね。

実行するとこんな感じです:

$ sudo /usr/local/bin/bundle exec ruby examples/lottery.rb 
Winner: 17

何が言いたいかというと、明日のイベントで『入門 eBPF』をプレゼントしますが、その抽選でeBPFを使う予定です。eBPFの実用性を示すために...。

engineercafe.connpass.com

そう!イベントのPRだったのです。まだ登録間に合いますので福岡市内に出られる方はぜひ。

という小ネタ日記...。