# What is the bpftime daemon? Function and Architecture Explained

> Discover the bpftime daemon a system monitoring service that boosts eBPF performance up to 10x by redirecting kernel events to userspace for improved efficiency and compatibility.

- Repository: [eunomia-bpf/bpftime](https://github.com/eunomia-bpf/bpftime)
- Tags: deep-dive
- Published: 2026-03-01

---

**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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/main.cpp)** – Parses CLI options into a `daemon_config` struct and calls `start_daemon(env)` to launch the service.
* **[`bpf_tracer.cpp`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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 initialization** – [`main.cpp`](https://github.com/eunomia-bpf/bpftime/blob/main/main.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 consumption** – `ring_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:

```bash
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:

```bash
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`](https://github.com/eunomia-bpf/bpftime/blob/main/daemon/kernel/bpf_tracer.bpf.c)) that captures events and a **userspace daemon** ([`daemon/user/bpf_tracer.cpp`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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`](https://github.com/eunomia-bpf/bpftime/blob/main/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.