Observability & Tracing

BPF maps

An eBPF program runs deep inside the kernel, fires briefly each time its hook triggers, and then it is gone — it has no permanent place of its own to keep a running total, and the user-space tool that wants the results lives in a completely separate world. A BPF map is the shared filing cabinet that bridges the two: a key-value data structure that lives in the kernel, survives between firings of the program, and can be read or written from BOTH the kernel-side eBPF program and a user-space process.

Concretely, a BPF map is created with a chosen type, a key size, and a value size. There are many map types tuned for different jobs: a hash map (look up a value by an arbitrary key, e.g. per-process counters keyed by PID), an array (fast integer-indexed slots), a per-CPU variant (each CPU gets its own copy so concurrent updates need no lock, and user space sums them afterward), a ring buffer or perf buffer (a queue for streaming events out to user space), and stack-trace maps (store captured call stacks). The eBPF program updates the map as events happen — incrementing a counter, appending an event — using approved helper calls that the verifier checks. Separately, the user-space tool periodically reads the map through the bpf() system call to collect and display the results. The map is the ONLY sanctioned channel for an eBPF program to keep state and to hand data back out.

It matters because it is the mechanism that turns a fleeting in-kernel program into a useful tool: the program does the cheap per-event work in the kernel (count, bucket, sample) and the map carries the aggregated answer to user space, instead of shipping every raw event out (which would be far more expensive). The honest caveats: maps have fixed, pre-sized capacity declared up front, so a hash map can fill up and start dropping new keys; the per-CPU types trade exact-at-every-instant reads for lock-free speed (user space must sum across CPUs); and a ring buffer can overflow and drop events under a flood, so a tool must be honest about possible loss rather than assuming it saw everything.

BPF_HASH(counts, u32, u64); // key = PID (u32), value = count (u64), kernel-side // on each event: counts[pid] += 1; // user space later: for k,v in counts: print(k, v) # reads via the bpf() syscall

A hash map keyed by PID accumulates counts in the kernel; user space reads the finished tallies through the bpf() syscall.

A map's capacity is fixed when it is created, so under heavy load a hash map can hit its size limit and silently fail to insert new keys — a tool reporting from a full map may be quietly under-counting.

Also called
eBPF mapsBPF mapBPF 映射BPF 對映