Project 1: Hello World Tracer (Your First BPF Program)
A series of one-liner BPF programs that trace system activity—counting system calls, printing function arguments, and measuring latencies.
Quick Reference
| Attribute | Value |
|---|---|
| Primary Language | bpftrace (DSL) |
| Alternative Languages | C with BCC, Python with BCC |
| Difficulty | Level 1: Beginner |
| Time Estimate | Weekend |
| Knowledge Area | BPF Basics / Tracing |
| Tooling | bpftrace |
| Prerequisites | Basic Linux command line, understanding of system calls |
What You Will Build
A series of one-liner BPF programs that trace system activity—counting system calls, printing function arguments, and measuring latencies.
Why It Matters
Before writing complex C programs, you need to understand what BPF can see. bpftrace lets you explore kernel attach points interactively. This is how Brendan Gregg, the author of most BPF tracing tools, does his exploratory work.
Core Challenges
- Understanding probe types → maps to kprobe vs tracepoint vs uprobe
- Reading kernel data structures → maps to accessing arguments and return values
- Aggregating data in-kernel → maps to BPF maps for counting and histograms
- Filtering events efficiently → maps to predicates and early returns
Key Concepts
- Probe Types: “BPF Performance Tools” Chapter 2 - Brendan Gregg
- bpftrace Language: bpftrace Reference Guide
- Tracepoints vs Kprobes: “Learning eBPF” Chapter 7 - Liz Rice
- Linux Tracing Overview: Brendan Gregg’s Linux Tracing Page
Real-World Outcome
# Count syscalls by process
$ sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'
Attaching 1 probe...
^C
@[sshd]: 127
@[bash]: 234
@[chrome]: 4521
@[firefox]: 8932
# Trace file opens with path
$ sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat {
printf("%s opened %s\n", comm, str(args->filename));
}'
bash opened /etc/passwd
vim opened /home/user/.vimrc
python opened /usr/lib/python3.10/os.py
# Histogram of read sizes
$ sudo bpftrace -e 'tracepoint:syscalls:sys_exit_read /args->ret > 0/ {
@bytes = hist(args->ret);
}'
@bytes:
[1] 234 |@@@@ |
[2, 4) 512 |@@@@@@@@@ |
[4, 8) 1024 |@@@@@@@@@@@@@@@@@@ |
[8, 16) 2341 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[16, 32) 1892 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
Implementation Guide
- Reproduce the simplest happy-path scenario.
- Build the smallest working version of the core feature.
- Add input validation and error handling.
- Add instrumentation/logging to confirm behavior.
- Refactor into clean modules with tests.
Milestones
- Milestone 1: Minimal working program that runs end-to-end.
- Milestone 2: Correct outputs for typical inputs.
- Milestone 3: Robust handling of edge cases.
- Milestone 4: Clean structure and documented usage.
Validation Checklist
- Output matches the real-world outcome example
- Handles invalid inputs safely
- Provides clear errors and exit codes
- Repeatable results across runs
References
- Main guide:
LEARN_BPF_EBPF_LINUX.md - “BPF Performance Tools” by Brendan Gregg