What is the bpftime daemon? Function and Architecture Explained

The bpftime daemon is a system-level monitoring service that intercepts eBPF-related syscalls and kernel events, redirecting their execution from the kernel to a userspace runtime for up to 10× performance improvement while maintaining compatibility with existing eBPF programs.

The bpftime daemon serves as the critical bridge between the Linux kernel and the userspace eBPF runtime in the eunomia-bpf/bpftime project. By capturing eBPF syscalls and uprobe events before they reach the kernel interpreter, this daemon enables high-performance execution of eBPF programs in userspace without requiring modifications to the target applications or eBPF code itself.

Core Functions of the bpftime daemon

The bpftime daemon operates by sitting between the kernel and bpftime’s userspace runtime, performing three critical functions that enable the project’s performance benefits.

Intercepting eBPF Syscalls and Kernel Events

The daemon intercepts eBPF-related syscalls including bpf(), perf_event_open(), and ioctl(), along with uprobe and uretprobe events generated in the kernel. This interception is handled by the kernel-space tracer component defined in daemon/kernel/bpf_tracer.bpf.c, which hooks these syscalls and writes event metadata into a ring buffer.

Redirecting Execution to Userspace

Once events are captured, the userspace daemon component reads from the ring buffer and redirects eBPF program execution to the bpftime userspace runtime instead of the kernel interpreter. This redirection happens in daemon/user/bpftime_driver.cpp, which bridges daemon events to the shared-memory bpftime runtime, allowing eBPF programs to run as userspace code while maintaining the same semantics as kernel eBPF.

Performance Optimization and Resource Sharing

The bpftime daemon enables several performance optimizations:

  • Zero-copy shared memory using Boost interprocess for communication between the kernel tracer and userspace driver, eliminating data copying overhead.
  • Map sharing between kernel-side and userspace-side BPF objects, allowing seamless data exchange without serialization.
  • Process filtering and whitelisting via PID, UID, and address filters to minimize overhead by only tracing selected processes.

Architecture and Key Components

The bpftime daemon consists of two primary components that work together to bridge kernel and userspace execution.

Kernel-Space Tracer

Located at daemon/kernel/bpf_tracer.bpf.c, this eBPF program loads into the kernel and hooks relevant syscalls. It captures events such as SYS_BPF, SYS_PERF_EVENT_OPEN, BPF_PROG_LOAD_EVENT, and EXEC_EXIT, writing them to a perf event ring buffer for consumption by the userspace component.

Userspace Daemon Components

The userspace portion consists of several key files in daemon/user/:

  • main.cpp – Parses CLI options into a daemon_config struct and calls start_daemon(env) to launch the service.
  • bpf_tracer.cpp – Contains the core event loop that loads the kernel tracer, configures filters, sets up the ring buffer, and processes events via handle_event_rb and bpf_event_handler.
  • bpftime_driver.cpp – Bridges daemon events to the bpftime runtime, creating maps and loading programs into the shared-memory region at /dev/shm/bpftime_maps_shm.

How the bpftime Daemon Works: Step-by-Step

The daemon follows a precise initialization and event-processing workflow:

  1. Program initializationmain.cpp parses CLI arguments including PID filters (-p), UID filters (-u), and whitelist addresses (-w), storing them in a daemon_config structure.

  2. Loading the kernel tracer – The start_daemon function calls bpf_tracer_bpf__open() to load the eBPF object, then injects configuration values (PID filters, replace-program flags) into the BPF object's read-only data section.

  3. Placeholder setup – If needed, the daemon writes embedded placeholder bytes to /a to serve as a dummy executable for uprobes.

  4. Whitelist configuration – When env.whitelist_enabled() returns true, the daemon populates the whitelist_hook_addr map with user-provided addresses to limit which uprobes trigger userspace execution.

  5. Attaching BPF programs – The kernel tracer attaches via bpf_tracer_bpf__attach and begins emitting events to the perf-event ring buffer.

  6. Event consumptionring_buffer__new creates a consumer that invokes handle_event_rb for each event; the bpf_event_handler forwards these events to the bpftime_driver.

  7. Process lifecycle tracking – The daemon periodically reads the exec_start map to detect long-lived processes and generates EXEC_EXIT events upon process termination.

  8. Shutdown – On SIGINT, the daemon sets exiting = 1, breaks the polling loop, frees the ring buffer, and destroys the BPF object.

Running the bpftime Daemon

Start the daemon directly from the command line with filtering options:

sudo SPDLOG_LEVEL=Debug build/daemon/bpftime_daemon -p 1234 -w 0x401234
  • -p limits tracing to a specific PID
  • -u filters by UID
  • -w whitelists specific uprobe addresses (hex format)
  • -v enables verbose logging

In another terminal, attach to a target program:

sudo SPDLOG_LEVEL=Debug ~/.bpftime/bpftime start ./example/malloc/victim

The daemon automatically creates the shared-memory region /dev/shm/bpftime_maps_shm and maps kernel file descriptors to userspace handler IDs, enabling the target program to access the same map contents as the kernel would.

Summary

  • The bpftime daemon intercepts eBPF syscalls and kernel events, redirecting them to a userspace runtime for significant performance gains.
  • It consists of a kernel-space tracer (daemon/kernel/bpf_tracer.bpf.c) that captures events and a userspace daemon (daemon/user/bpf_tracer.cpp) that processes them.
  • The daemon enables zero-copy shared memory communication, map sharing between kernel and userspace, and fine-grained filtering by PID, UID, or address.
  • Initialization involves loading the kernel tracer, configuring filters, attaching to the ring buffer, and forwarding events to the bpftime driver for userspace execution.

Frequently Asked Questions

What syscalls does the bpftime daemon intercept?

The bpftime daemon intercepts eBPF-related syscalls including bpf(), perf_event_open(), and ioctl(), along with uprobe and uretprobe events. These interceptions are handled by the kernel-space tracer defined in daemon/kernel/bpf_tracer.bpf.c, which writes event metadata to a ring buffer for userspace processing.

How does bpftime achieve 10× performance improvement?

The daemon redirects eBPF program execution from the kernel interpreter to a userspace runtime, eliminating kernel-user context switches and leveraging zero-copy shared memory via Boost interprocess. By running eBPF programs in userspace and sharing maps between kernel and userspace components without serialization overhead, the system achieves significant latency reductions for many workloads.

What is the difference between the kernel tracer and userspace daemon?

The kernel-space tracer (daemon/kernel/bpf_tracer.bpf.c) is an eBPF program loaded into the kernel that hooks syscalls and writes events to a ring buffer. The userspace daemon (daemon/user/bpf_tracer.cpp) runs as a standard process that reads from this ring buffer, configures filters, and forwards events to the bpftime runtime for userspace execution.

How do I filter which processes the bpftime daemon monitors?

Use command-line flags when starting the daemon: -p to filter by specific PID, -u to filter by UID, and -w to whitelist specific uprobe addresses in hexadecimal format. These filters are injected into the kernel tracer's read-only data section during initialization, ensuring only selected processes trigger userspace execution and minimizing system overhead.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →