eBPF Course · Reference

Glossary

Compressed definitions for every term in the course — quick reference, built to print.

🎯 Observability & tracing with bpftrace

Every term you meet in the lessons, defined in plain language for someone new to kernels — one to three sentences each, plus a one-liner on why it matters or where you run into it. Terms are alphabetized; each has an #id anchor so the lessons can deep-link straight to it. Tags mark bpftrace items and the one out-of-scope term.

A
Aggregation
Summarizing many events into a compact result inside the kernel — a count, sum, average, min/max, or histogram — instead of shipping every raw event to user space. In bpftrace you aggregate into a map, e.g. @bytes = sum(args.count) or @[comm] = count(). Why it matters: aggregation is what makes tracing cheap enough for production — the kernel does the math, so you read a tidy table, not a firehose.
args bpftrace builtin
A struct holding the named arguments of the probed event — the fields of a tracepoint, or the typed arguments of a kernel/user function. You read them by name, e.g. args.filename or args.count. Where you meet it: tracepoint:syscalls:sys_enter_openat { printf("%s\n", str(args.filename)); } — far friendlier than positional arg0..argN.
arg0 … argN bpftrace builtin
The raw, positional arguments of a probed function as 64-bit values: arg0 is the first argument, arg1 the second, and so on. Used with kprobes/uprobes, where there is no type info to give you named args. Heads-up: they're untyped integers — you often wrap them, e.g. str(arg0) to read a string pointer, and you must know the function's signature yourself.
B
BCC (BPF Compiler Collection)
A toolkit (project iovisor/bcc) with a large collection of ready-made tracing tools plus C and Python interfaces for building your own. You write the kernel half in C and the user-space orchestration in Python (the Python front-end is now de-emphasized in favor of libbpf-style C). Where you meet it: Brendan Gregg's guidance — "bcc is ideal for complex tools and daemons"; reach for it when a bpftrace one-liner isn't enough.
BEGIN / END probes bpftrace
Special probes that fire once at program start (BEGIN) and once at program exit (END), not tied to any kernel event. Use BEGIN to print a header or initialize state, and END to print final results. Where you meet it: END { print(@); } — by default bpftrace already prints maps on exit, but END lets you control or format the summary.
BPF (classic BPF / cBPF) & the name
BPF originally stood for Berkeley Packet Filter, a tiny in-kernel virtual machine from 1992 for filtering network packets (e.g. for tcpdump). That original form is now called classic BPF or cBPF to distinguish it from the modern eBPF. Why it matters: it explains the name's history — eBPF kept the "BPF" letters but long outgrew packet filtering, so today "BPF" and "eBPF" are used interchangeably and no longer stand for anything. ebpf.io
BPF bytecode
The low-level, machine-independent instruction format the kernel expects an eBPF program to be loaded as. A compiler (or bpftrace) turns your high-level source into this bytecode, which the kernel then verifies and runs. Why it matters: bytecode is the universal "shipping format" — it's what the verifier checks and what the JIT turns into native CPU instructions.
bpf() syscall
The single Linux system call through which all eBPF operations flow: loading a program, creating and reading/writing maps, attaching programs, and more — selected by a command argument. Where you meet it: you rarely call it by hand — bpftrace, BCC, and libbpf call bpf() for you — but it's the kernel doorway every eBPF tool uses. bpf(2)
BPF virtual machine
The abstract instruction-set "machine" that eBPF bytecode targets: a small set of registers and instructions the kernel knows how to validate and execute. It's a sandbox model, not a real CPU — programs run inside it under the kernel's control. Why it matters: the VM abstraction is what lets the same bytecode be verified for safety and then JIT-compiled to whatever real CPU you're on.
bpftrace the course's anchor tool
A high-level tracing language and front-end for eBPF: you write short, awk-like scripts (probe /filter/ { action }) and bpftrace compiles, loads, and runs them for you. Created by Alastair Robertson; ideal for ad-hoc one-liners and short scripts. Why it matters: it's the fastest way to ask the running kernel a question — "if you want to program your own, start with bpftrace."
BTF (BPF Type Format)
A metadata format that encodes type and debug information (struct layouts, function signatures, source lines) about BPF programs and the kernel itself. Modern kernels ship their own BTF so tools can learn the exact shape of kernel data structures at runtime. Why it matters: BTF is the foundation of CO-RE — it's how a program written once can correctly find a struct field even on a kernel whose layout differs. docs.kernel.org/bpf
Builtin bpftrace
A read-only variable bpftrace provides automatically inside a probe, giving context about the current event — such as comm, pid, nsecs, cpu, retval, or kstack. Where you meet it: builtins are the nouns of a bpftrace one-liner — you reference them directly, no setup required.
C
CAP_BPF / CAP_PERFMON
Fine-grained Linux capabilities (since kernel 5.8) that grant just the privileges eBPF needs, instead of full root (CAP_SYS_ADMIN). CAP_BPF allows loading programs and creating maps; CAP_PERFMON allows the performance-monitoring side (perf events and tracing programs). Why it matters: together they let a tracing tool run without giving it the entire kernel — the least-privilege way to permit bpftrace. In practice many setups still just use sudo. capabilities(7)
comm bpftrace builtin
The name of the current process (its "command" — the short executable name, e.g. nginx or node). Where you meet it: grouping by who's responsible — @[comm] = count() tells you which programs are hitting a probe most.
CO-RE (Compile Once – Run Everywhere)
A technique that lets a single compiled eBPF program run unchanged across many kernel versions, even when internal struct layouts differ. The compiler records what fields the program needs; using BTF, the loader "relocates" those field accesses to match the kernel actually running. Why it matters: CO-RE killed the old pain of recompiling a tool against each machine's kernel headers — it's why portable eBPF tools (libbpf-based) ship as one binary.
cpu bpftrace builtin
The ID of the logical CPU (processor) on which the probe is currently firing. Where you meet it: spotting CPU imbalance or per-core behavior — e.g. @[cpu] = count().
curtask bpftrace builtin
A pointer to the kernel's task_struct for the currently running thread — the kernel's big bookkeeping record for a task. Where you meet it: advanced scripts that read scheduler or process fields directly from the task struct; most one-liners never need it.
D
Dynamic vs static tracing
Dynamic tracing instruments any function on the fly with no prior planning (kprobes, uprobes) — flexible, but the function names/arguments can change between versions. Static tracing uses instrumentation points the developers deliberately placed and named (tracepoints, USDT) — fewer, but a stable contract. Rule of thumb: prefer a static tracepoint when one exists; fall back to a dynamic probe to reach anywhere else.
E
eBPF
A Linux-kernel technology that runs small, sandboxed programs in a privileged context (inside the kernel) in response to events, safely and without changing kernel source or loading a module. "eBPF" is now a standalone term — it no longer stands for anything (see BPF for the history). Why it matters: it's the whole foundation — eBPF is how bpftrace can watch what the kernel and your programs are doing, live, with near-zero overhead. ebpf.io
eBPF program
The actual unit of code that runs in the kernel: event-driven, attached to a hook, and executed whenever that hook is reached. It's loaded as bytecode, checked by the verifier, and usually JIT-compiled. Where you meet it: each bpftrace probe action becomes one eBPF program behind the scenes — you write the script, bpftrace produces the programs.
Event
Something happening in the system that an eBPF program can react to — a function being entered or returning, a syscall, a timer tick, a tracepoint firing. eBPF is fundamentally event-driven: no event, no execution. Why it matters: framing tracing as "run this tiny program every time event X happens" is the core mental model for everything in the course.
F
Flame graph
A visualization of sampled stack traces: each box is a function, its width is how often that function (and its callees) appeared in the samples, and depth shows the call stack. Invented by Brendan Gregg. Where you meet it: the standard way to read CPU profiles — the widest boxes are where time is going. brendangregg.com
func bpftrace builtin
The name of the function the current probe is attached to. Where you meet it: one probe spanning many functions (wildcards) — printf("%s\n", func) tells you which one actually fired.
H
Helper function
A predefined kernel function that an eBPF program is allowed to call — a small, stable, allow-listed API. Helpers do things a sandboxed program can't do directly: read/write maps, get the current time, fetch the pid, copy memory safely, capture a stack, and so on. Why it matters: helpers are the program's only "system calls" — they're how a verified, sandboxed program safely reaches the outside world. ebpf.io
Histogram — hist() / lhist() bpftrace
Aggregation functions that bucket values and print a text bar chart. hist(v) uses power-of-two (log2) buckets — great for wide-ranging values like latency. lhist(v, min, max, step) is a linear histogram with evenly sized buckets you choose. Where you meet it: @ = hist(retval) to see a latency distribution at a glance — the shape (and outliers) matter more than an average.
Hook / attach point
A defined place in the kernel or a program where an eBPF program can be attached so it runs when execution reaches there. Pre-defined hooks include syscalls, function entry/exit, and tracepoints; kprobes and uprobes let you create hooks almost anywhere. Why it matters: picking the right hook is the act of tracing — it decides exactly which events your program sees.
I
interval probe bpftrace
A probe that fires on a fixed time interval on a single CPU — e.g. interval:s:1 once per second. Used for periodic output and script-level timers. Where you meet it: live dashboards — print and clear your maps every second: interval:s:1 { print(@); clear(@); }. (Contrast with profile, which fires on all CPUs.)
J
JIT compiler (Just-In-Time)
The kernel step that translates verified eBPF bytecode into the native machine instructions of the current CPU, so the program runs at near-native speed instead of being interpreted. Why it matters: JIT is a big reason eBPF tracing is cheap enough for production — your probe becomes real CPU code, not a slow interpreter loop. ebpf.io
K
kprobe bpftrace probe
A dynamic probe that fires when a kernel function is entered. You can attach one to almost any kernel function by name, e.g. kprobe:vfs_read, and read its arguments via arg0..argN. Where you meet it: reaching into kernel internals when no tracepoint covers what you need — the flexible, "anywhere" probe.
kretprobe bpftrace probe
The companion to a kprobe that fires when the kernel function returns, giving you its retval. Pair it with the kprobe to measure how long the function took. Where you meet it: latency measurement — timestamp on kprobe, subtract on kretprobe, feed the delta to hist().
kstack / ustack bpftrace builtin
The current stack trace: kstack is the kernel-side call stack, ustack the user-space call stack of the running thread. Both are capturable as map keys. Where you meet it: answering "how did we get here?" — @[kstack] = count() counts code paths and is the raw material for a flame graph.
L
libbpf
The standard C library for loading and managing eBPF programs from user space. It handles talking to the bpf() syscall, applying CO-RE relocations via BTF, and attaching programs. Where you meet it: the modern foundation for portable, compiled eBPF tools (and the direction BCC now points); you'll see it named when people talk "libbpf + CO-RE." Out of scope to write here, but good to recognize.
lhist() — linear histogram bpftrace
See Histogram. lhist(value, min, max, step) places values into evenly sized buckets between min and max. Where you meet it: when you want uniform buckets (e.g. counts 0–20 by 1s) rather than hist()'s widening power-of-two ranges.
M
Map
A kernel data structure (hash table, array, ring buffer, stack-trace store, and more) that eBPF programs use to store state and to share data with user space. Maps can be read and written both by the in-kernel program and by the user-space tool via the bpf() syscall. Why it matters: maps are the bridge — every bpftrace @variable is a map, and that's how your one-liner's results get from kernel to your terminal. ebpf.io
N
nsecs bpftrace builtin
A timestamp in nanoseconds from a monotonic kernel clock (it counts up steadily; it's not wall-clock time). Where you meet it: timing things — record nsecs at the start of an event, subtract at the end to get a precise duration.
O
On-CPU vs off-CPU analysis
On-CPU analysis studies where threads spend time running on a CPU (classic profiling). Off-CPU analysis studies time threads spend blocked off-CPU — waiting on I/O, locks, timers, or the scheduler — captured with stack traces. Why it matters: they're complementary, so 100% of a thread's time can be explained. If your code is slow but the CPU is idle, the answer is in off-CPU time, not the on-CPU profile. brendangregg.com
P
Perf buffer
The older mechanism for streaming per-event data from kernel to user space, using one ring buffer per CPU. Simple and widely supported, but it can waste memory and lose ordering across CPUs. Why it matters: it's the predecessor to the ring buffer; you'll see it in older tools and BCC examples.
pid / tid bpftrace builtin
pid is the process ID (the kernel's thread-group ID — the number you see in ps); tid is the thread ID of the specific thread that triggered the event. Where you meet it: filtering to one process (/pid == 1234/) or attributing events per-thread vs per-process.
Predicate / filter bpftrace
A condition in /slashes/ right after a probe; the action runs only when it's true. Example: kprobe:vfs_read /comm == "node"/ { ... } fires only for the node process. Why it matters: predicates cut noise at the source — you filter in the kernel, so you process and print far less.
Probe
In bpftrace, the part of a statement that names what to instrument and when to fire — i.e. the hook. Each statement is probe /predicate/ { action }; a probe has a type (kprobe, tracepoint, uprobe, profile, …) and a target. Why it matters: the probe is the first thing you write and the most important decision — choose it and you've chosen your data.
profile probe bpftrace
A probe that fires on a timed interval across all CPUs at once — timed sampling. For example profile:hz:99 samples 99 times per second on every CPU. Where you meet it: CPU profiling — sample stacks and feed them to a flame graph. (Contrast interval, which fires on one CPU.)
R
retval bpftrace builtin
The return value of the probed function — available in return probes (kretprobe / uretprobe) and in tracepoint exit events. Where you meet it: checking outcomes — count failed syscalls with /retval < 0/, or measure how long a call took via its return.
Ring buffer (BPF ring buffer)
The newer (Linux 5.8+) mechanism for streaming per-event data to user space: a single shared multi-producer/single-consumer buffer across all CPUs. It preserves event ordering and uses memory more efficiently than the per-CPU perf buffer. Why it matters: it's the modern default for sending raw events out of the kernel — correct ordering matters when you correlate things like fork → exec → exit. nakryiko.com
S
System call (syscall)
The controlled doorway a user-space program uses to ask the kernel to do something privileged — open a file, read, write, allocate memory, send on a socket. Each is a numbered request like openat or read. Where you meet it: syscalls are the richest tracing target — "what files is this opening?" is just tracing the openat syscall tracepoint.
T
tracepoint bpftrace probe
A static, developer-placed instrumentation point in the kernel with a stable name and documented arguments — e.g. tracepoint:syscalls:sys_enter_openat. Arguments are read by name via args. Why it matters: tracepoints are the preferred kernel probe — a stable contract, so your script keeps working across kernel versions where a kprobe might break.
U
Unprivileged eBPF
Whether a non-root user may call bpf() at all. Most distributions now disable it (the kernel.unprivileged_bpf_disabled sysctl), so loading programs requires root or CAP_BPF/CAP_PERFMON. Why it matters: it's why bpftrace commands need sudo — the kernel gates tracing behind privilege for safety. docs.kernel.org
uprobe bpftrace probe
The user-space equivalent of a kprobe: a dynamic probe that fires when a function in a user-space binary or library is entered, e.g. uprobe:/bin/bash:readline. Where you meet it: tracing inside an application or library — note it adds some latency to the traced program, so use predicates to keep it targeted.
uretprobe bpftrace probe
Fires when a user-space function returns, giving its retval — the user-space partner to kretprobe. Where you meet it: timing a user function (entry on uprobe, exit on uretprobe) or inspecting what it returned.
USDT (User Statically-Defined Tracing)
Stable, developer-placed tracepoints compiled into a user-space program (databases, language runtimes, etc.). The user-space counterpart to kernel tracepoints — named, documented, low-overhead. Where you meet it: tracing application-level events an app deliberately exposes (e.g. a query start), instead of guessing at internal functions with a uprobe.
USE method
A performance checklist by Brendan Gregg: for every resource, check Utilization (how busy it was), Saturation (how much extra work is queued waiting), and Errors. Walk every resource — CPU, memory, disks, network — through U, S, E. Why it matters: it's a fast, systematic way to find bottlenecks; it tells you which resource to point your tracing at next. brendangregg.com
User space vs kernel space
Two protected worlds. Kernel space is the privileged core that manages hardware, memory, and processes; user space is where your applications run, isolated from each other and the kernel. They communicate through syscalls. Why it matters: this boundary is the heart of the course — eBPF runs in the kernel, which is exactly why a bpftrace probe can see across all of user space at once, no app changes needed.
V
Verifier
The kernel safety checker every eBPF program must pass before it runs. It proves the program will terminate (no unbounded loops), never reads uninitialized memory or accesses out of bounds, and stays within complexity limits — by analyzing all possible execution paths. Why it matters: the verifier is why running eBPF in the kernel is safe — a rejected program simply won't load. Note it checks safety, not what the program is trying to do. ebpf.io
X
XDP (eXpress Data Path) out of scope
An eBPF hook at the very earliest point of network packet receive, used for ultra-fast packet processing (filtering, load balancing, DDoS drop) before the kernel's normal networking stack. Why it's here: you'll see "XDP" everywhere in eBPF writing — but it's networking, which this observability-focused course deliberately leaves out. Defined so the term isn't a mystery.
💡 How to use this glossary Every term has a stable #id anchor — the lessons link straight here (e.g. glossary.html#verifier). Press Ctrl/⌘+F to find a term, or use the A–Z bar to jump. Print to PDF for an offline cheat sheet — the layout is built for it.