DEV Community

Cover image for How a 2GB Flash Drive Led Me to Rust, Linux Internals and eBPF
Josiah Mbao
Josiah Mbao

Posted on

How a 2GB Flash Drive Led Me to Rust, Linux Internals and eBPF

A few months ago, my dad gave me his old work laptop.

I was excited. A new machine to call my own.

So naturally, I factory-reset the thing.

Then I did something slightly more drastic: I got rid of Windows.

There was just one problem.

The only flash drive I had was around 2 GB, which wasn't going to be enough to put Windows back on the machine.

So I started wondering:

What operating system is small enough to fit on a 2 GB flash drive?

Enter Arch Linux.

Falling down the Arch Linux rabbit hole

Getting Arch Linux running was not exactly a one-click installation.

It took me about two days to get the ISO, boot from it, partition the disk, install the system, configure everything, and eventually get to something usable.

And by "usable," I mean a purely terminal-based environment.

No desktop environment.

No polished GUI.

Just a shell and a Linux system that I was now responsible for figuring out.

A week later, a friend who had been using Arch longer than I had introduced me to Hyprland.

That opened another rabbit hole.

I started customizing my desktop, configuring the terminal, installing tools, tweaking things, and generally enjoying how much control Linux gave me over my own machine.

Eventually, I wanted to know how the machine itself was doing.

How much CPU was being used?

How much memory?

What processes were running?

So I reached for the obvious tools:

top
htop
Enter fullscreen mode Exit fullscreen mode

They did exactly what I needed.

But then I had another thought:

If Linux is this customizable, could I build my own tool to answer the question of how my machine is doing?

That question eventually became Pulse.

What is Pulse?

Pulse is a Linux observability TUI written in Rust.

It started as a small experiment to learn more about Linux internals and terminal applications.

Instead of simply using existing monitoring tools, I wanted to understand where the information they displayed actually came from.

That led me to /proc.

/proc: My first look under the hood

Linux exposes a huge amount of information about the running system through the proc filesystem.

For example:

/proc/
├── stat
├── meminfo
├── loadavg
└── <pid>/
    ├── stat
    ├── status
    └── ...
Enter fullscreen mode Exit fullscreen mode

Pulse reads information from these interfaces and turns the raw data into metrics that can be displayed in the terminal.

Pulse v0.1 - Initial demo
[Pulse v0.1 - Early version]

This was the first point where the project became more interesting than simply building another TUI.

I started realizing that a metric like CPU utilization isn't necessarily something you can just ask Linux for.

You might instead get raw counters, understand what those counters represent, take measurements over time, and calculate the value you actually want.

For example, /proc/stat exposes CPU time counters:

cpu  1234 56 789 10234 12 0 34 0 0 0
Enter fullscreen mode Exit fullscreen mode

Pulse can use this information to derive useful metrics about CPU activity.

That meant I wasn't just displaying system information.

I was learning how the system exposes that information in the first place.

Why Rust?

I'll admit something:

I love Rust and will find any excuse to use it.

But in this case, I actually had a pretty good excuse.

Pulse is a Linux observability tool, which puts it fairly close to the systems programming domain.

And guess what else works well in systems programming?

Rust.

I wanted Pulse to teach me more than just Linux. I also wanted to become significantly more comfortable writing Rust, particularly when dealing with lower-level concepts, concurrency, processes, memory, and long-running applications.

Rust's memory-safety guarantees were especially attractive for a tool interacting with a constantly changing system.

Processes can start and disappear.

Files can change between reads.

System state can change while you're rendering it.

The application itself is continuously collecting data and updating the UI.

Rust gives me strong guarantees around memory safety while still allowing me to work fairly close to the system.

More importantly, Rust forced me to think differently about how I structure programs.

Pulse became one of my excuses to go deeper into the language.

From /proc to observability

Once Pulse could render system metrics from /proc, I started asking another question:

What else can I monitor?

And then:

Can I do it faster?

The more I looked into Linux internals, the more I realized that there was a much bigger world underneath what tools like top and htop expose.

/proc is incredibly useful for understanding system state.

But I wanted Pulse to eventually understand events happening inside the system.

Processes being created.

System calls being made.

Network activity.

Kernel functions being executed.

And potentially much more.

That's when I stumbled into eBPF.

Enter eBPF

eBPF opened up an entirely different side of Linux observability for me.

At a high level, eBPF lets you run small programs in the Linux kernel to observe and respond to events happening inside the system, without having to modify the kernel's source code.

That means you can attach programs to things like system calls, network events, tracepoints, and other kernel activity, collect information about what's happening, and send that data right back to a user-space application.

Instead of only asking the system:

"What is happening right now?"

I could start asking:

"What just happened, and why?"

Conceptually, Pulse started evolving from something like this:

        Linux
          │
        /proc
          │
      Collect data
          │
        Pulse
          │
         TUI
Enter fullscreen mode Exit fullscreen mode

towards:

                  Linux Kernel
                       │
              ┌────────┴────────┐
              │                 │
            /proc              eBPF
              │                 │
              └────────┬────────┘
                       │
                   Collectors
                       │
                   Pulse Core
                       │
                      TUI
Enter fullscreen mode Exit fullscreen mode

I'm currently only using eBPF for a small subset of Pulse's functionality, but getting those first pieces working changed how I thought about the project.

Pulse wasn't just a system monitor anymore.

It was becoming a playground for learning Linux observability.

What I've learned building Pulse

The biggest lesson hasn't actually been Rust.

It's been realizing how much abstraction exists between what I see on my screen and what the operating system is actually doing.

Before Pulse, I could run:

htop
Enter fullscreen mode Exit fullscreen mode

and see CPU utilization, memory usage, processes, and other information.

Now I have a much better appreciation for the chain of things happening underneath those numbers.

Linux exposes information through interfaces like /proc.

Applications interpret that information.

Metrics often have to be calculated from raw counters.

And with eBPF, you can go even deeper and observe activity directly within the kernel.

Building Pulse has basically been an excuse to keep peeling away those layers.

Trace Lens - eBPF in action!
[Trace Lens - eBPF in action]

Every time I think I've reached the bottom, I find another layer underneath.

What surprised me

One of the things I didn't expect when I started Pulse was how quickly a seemingly simple project could lead into completely different areas of computer science.

I started with:

"How much CPU am I using?"

That led to:

/proc
  ↓
Linux internals
  ↓
Systems programming
  ↓
Rust
  ↓
Observability
  ↓
eBPF
  ↓
Kernel instrumentation
Enter fullscreen mode Exit fullscreen mode

And that's probably my favorite thing about software engineering.

You can start with a small question and keep digging until you find an entirely different layer underneath.

What's next?

Pulse is still very much a work in progress.

I'm particularly interested in expanding its eBPF instrumentation.

Right now I'm only tracking a couple of things through eBPF, but I'm learning that there's a lot more that can be observed.

Networking is one area I'm particularly interested in exploring.

There are also plenty of other kernel-level events and subsystems that could eventually become part of Pulse.

I don't have a final definition of what Pulse is supposed to become yet.

And honestly, I like that.

The project started because I wanted to answer a simple question:

How is my machine doing?

It has gradually turned into a much more interesting question:

What's actually happening inside my machine?

That's the question I want to keep exploring.

Final thoughts

Pulse started as a small /proc-based system monitor I was building to learn more about Linux internals and terminal applications.

It has since become my playground for learning:

  • Linux systems programming

  • Rust

  • observability

  • eBPF

  • kernel instrumentation

  • terminal UI development

And I'm nowhere near done.

The project is open source, and I'll keep building it as I learn more about what's happening underneath the abstractions we normally take for granted.

Pulse v0.8 - Latest Pulse demo
[Pulse v0.8 - Latest version]

If you're interested in Linux internals, Rust, or observability, the project is here:

GitHub logo josiah-mbao / pulse

Linux observability TUI built in Rust, combining /proc telemetry with real-time eBPF kernel tracing

Pulse

Pulse mascot

An open-source Linux observability TUI built with Rust.
Combining low-overhead /proc telemetry with real-time eBPF kernel lifecycle tracing.

🌐 Live Website & Documentation

CI Status License Linux eBPF


🎭 Visual Evolution

Latest — v0.8 "Kernel Trace"

Latest Demo

Original — v0.1

Original Demo

Live terminal recordings generated with asciinema.


🌱 The Origin Story

Pulse started on a whim and a hand-me-down laptop.

After reviving an old machine with Arch Linux and building a custom Hyprland desktop, I found myself constantly reaching for top and htop whenever something felt slow.

Watching thousands of values update in real time sparked a question:

How can these tools continuously observe an entire Linux system without becoming the bottleneck themselves?

Arch Linux encourages understanding your system from the ground up, so I decided to extend that philosophy to application development.

Rather than treating Linux as a black box, I wanted to understand how observability works from the kernel upward—how processes are born…





Built because I wanted to know what my machine was actually doing.

Top comments (0)