Brendan Gregg | 239e863 | 2016-07-25 15:02:32 -0700 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # This is a Hello World example that uses BPF_PERF_OUTPUT. |
| 4 | |
| 5 | from bcc import BPF |
| 6 | import ctypes as ct |
| 7 | |
| 8 | # define BPF program |
| 9 | prog = """ |
| 10 | #include <linux/sched.h> |
| 11 | |
| 12 | // define output data structure in C |
| 13 | #define MSG_MAX 32 |
| 14 | struct data_t { |
| 15 | u32 pid; |
| 16 | u64 ts; |
| 17 | char comm[TASK_COMM_LEN]; |
| 18 | }; |
| 19 | BPF_PERF_OUTPUT(events); |
| 20 | |
| 21 | int hello(struct pt_regs *ctx) { |
| 22 | struct data_t data = {}; |
| 23 | |
| 24 | data.pid = bpf_get_current_pid_tgid(); |
| 25 | data.ts = bpf_ktime_get_ns(); |
| 26 | bpf_get_current_comm(&data.comm, sizeof(data.comm)); |
| 27 | |
| 28 | events.perf_submit(ctx, &data, sizeof(data)); |
| 29 | |
| 30 | return 0; |
| 31 | } |
| 32 | """ |
| 33 | |
| 34 | # load BPF program |
| 35 | b = BPF(text=prog) |
| 36 | b.attach_kprobe(event="sys_clone", fn_name="hello") |
| 37 | |
| 38 | # define output data structure in Python |
| 39 | TASK_COMM_LEN = 16 # linux/sched.h |
| 40 | MSG_MAX = 32 |
| 41 | class Data(ct.Structure): |
| 42 | _fields_ = [("pid", ct.c_ulonglong), |
| 43 | ("ts", ct.c_ulonglong), |
| 44 | ("comm", ct.c_char * TASK_COMM_LEN)] |
| 45 | |
| 46 | # header |
| 47 | print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE")) |
| 48 | |
| 49 | # process event |
| 50 | start = 0 |
| 51 | def print_event(cpu, data, size): |
| 52 | global start |
| 53 | event = ct.cast(data, ct.POINTER(Data)).contents |
| 54 | if start == 0: |
| 55 | start = event.ts |
| 56 | time_s = (float(event.ts - start)) / 1000000000 |
| 57 | print("%-18.9f %-16s %-6d %s" % (time_s, event.comm, event.pid, |
| 58 | "Hello, perf_output!")) |
| 59 | |
| 60 | # loop with callback to print_event |
| 61 | b["events"].open_perf_buffer(print_event) |
| 62 | while 1: |
| 63 | b.kprobe_poll() |