vimer linux kernel 爱好者

BPF-bcc usage

2018-05-13
bpf

The bolg post adoped from bcc/docs/ mainly. You just glance it.

lesson 1

from bcc import BPF
import signal
import sys

def bpf():
    BPF(text='''
    int kprobe__sys_sync(void *ctx)
    { bpf_trace_printk("Hello, yubo\\n");
    return 0;}'''
    ).trace_print()

def signal_handler(signal, frame):
    print('You pressed Ctrl+c!')
    bpf()
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
print('press Ctrl+c')
signal.pause()

lesson 2

from bcc import BPF
prog = """
int hello(void *ctx)
{
/*  bpf_trace_printk will call it:
 *  /sys/kernel/debug/tracing/trace_pipe
 */
    bpf_trace_printk("Hello, yubo\\n");
    return 0;
}
"""

# load BPF program
b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello")

print("%-18s %-16s %-6s %s" % ("TIME(S)", "COMM", "PID", "MESSAGE"))

while 1:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    except ValueError:
        continue
    print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))

Here, this time we declare the C program as a variable : prog.

  1. hello() On a probe to execute a C program defined here.Maybe you need add _always_inline function attribute to it.

  2. b.attach_kprobe() : creates a kprobe for the sys_clone() kernel function, which will execute our defined hello C program.

  3. b.trace_fields()  Returns a fixed set of fields from trace_pipe,which similar to trace_print() .We should switch to BPF_PERF_OUTPUT()

lesson 4

from bcc import BPF

b = BPF(text="""
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>

BPF_HASH(last);

int do_trace(struct pt_regs *ctx){
    u64 ts, *tsp, delta, key = 0;
    /* attempt to read stored timestamp */
    tsp = last.lookup(&key);
    if (tsp != 0) {
        delta = bpf_ktime_get_ns() - *tsp;
        if (delta < 1000000000) {
            bpf_trace_printk("%d\\n", delta / 1000000);
        }
        last.delete(&key);
    }
    /* update stored timestamp */
    ts = bpf_ktime_get_ns();
    last.update(&key, &ts);
    return 0;
}
""")
b.attach_kprobe(event="sys_sync", fn_name="do_trace")
print("Tracing for quick sync's ... Ctrl -c to end ")

# format output
start = 0
while 1:
    (task, pid, cpu, flags, ts, ms) = b.trace_fields()
    if start == 0:
        start = ts
    ts = ts - start
    print("At time %.2f s: multiple syncs detected, last %s ms ago " % (ts,ms))

Here, we introduce some new usage.BPF_HASH(last) creates a BPF map object that is a hash called “last”.It is defaults key and value types of u64 last.lookup(&key): Lookup the key from the hash.last.delete(&key)Delete the key from the hash.last.update(&key, &ts) Associate the valuein the 2nd argument to the key.

Please note: the b.trace_fields is a kernel debug trace pipe and return a tuple of the fields(task, pid, cpu,flags, timestamp, msg).This is trace debug.


下一篇 xdp简介

Comments

Content