Project 2: System Call Monitor (Your First C BPF Program)

A complete BPF program in C that monitors system calls, counts them by type and process, and displays real-time statistics—essentially your own version of strace but with kernel-level efficiency.

Quick Reference

Attribute Value
Primary Language C (libbpf)
Alternative Languages Go (cilium/ebpf), Rust (aya)
Difficulty Level 2: Intermediate
Time Estimate 1-2 weeks
Knowledge Area BPF Programming / System Calls
Tooling libbpf, clang, bpftool
Prerequisites C programming, Project 1 completed, basic understanding of Linux syscalls

What You Will Build

A complete BPF program in C that monitors system calls, counts them by type and process, and displays real-time statistics—essentially your own version of strace but with kernel-level efficiency.

Why It Matters

This forces you to understand the complete BPF development workflow: writing BPF C code, compiling with clang, loading with libbpf, and communicating between kernel and userspace via maps.

Core Challenges

  • Setting up the BPF development environment → maps to clang, libbpf, kernel headers
  • Writing BPF-compatible C code → maps to verifier constraints, helper functions
  • Defining and using BPF maps → maps to data sharing between kernel and userspace
  • Loading and attaching programs → maps to libbpf skeleton, bpf() syscall

Key Concepts

Real-World Outcome

$ sudo ./syscall_monitor
PID     COMM            SYSCALL         COUNT   RATE/s
1234    nginx           read            15234   1523.4
1234    nginx           write           12892   1289.2
1234    nginx           epoll_wait       8923    892.3
5678    postgres        read            45123   4512.3
5678    postgres        futex           23891   2389.1
9012    chrome          mmap             3421    342.1
9012    chrome          munmap           2198    219.8

[Top syscalls last 10 seconds]
read:        123,456 (45.2%)
write:        89,123 (32.7%)
epoll_wait:   34,567 (12.7%)
futex:        15,234 (5.6%)
mmap:         10,234 (3.8%)

Implementation Guide

  1. Reproduce the simplest happy-path scenario.
  2. Build the smallest working version of the core feature.
  3. Add input validation and error handling.
  4. Add instrumentation/logging to confirm behavior.
  5. 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
  • “Learning eBPF” by Liz Rice