What it did
Build a terminal process monitor (like htop) from scratch in C++.
Reads /proc/stat, /proc/meminfo, /proc/[pid]/* continuously,
renders aggregate CPU%, memory, uptime, and a sortable per-process
table via ncurses.
The /proc API surface
| File | What |
|---|---|
/proc/stat | aggregate CPU jiffies (user, nice, system, idle, iowait) |
/proc/meminfo | RAM total/free/cached/buffers |
/proc/uptime | seconds since boot |
/proc/[pid]/stat | per-process CPU jiffies + state + start-time |
/proc/[pid]/status | per-process memory usage (RSS, VmSize) |
/proc/[pid]/cmdline | the full command line as a null-separated string |
/proc/[pid]/comm | the short command name |
CPU% per process is (process_jiffies_now - process_jiffies_then) / (total_cpu_jiffies_now - total_cpu_jiffies_then) — a delta over a
fixed sampling interval, never absolute.
What was actually tricky
cmdlineis null-separated. Reading it with>>gives you onlyargv[0]; you need to read the whole file and replace\0with spaces.- PIDs reuse. A process can die and a new one get the same PID between samples. Tracking by start-time + PID handles it.
- ncurses redraw flicker. Need to use
wclear()+ double-buffer rendering carefully or the screen tears.
What I’d do differently with hindsight
- Use
/proc/[pid]/iofor per-process disk I/O — htop’s modern view shows it; the project didn’t. - Test on different distros. The
/procschema is technically documented but I’ve hit edge cases on Alpine, Ubuntu, and Fedora where one column was off-by-one. - Replace ncurses with a TUI lib —
notcursesorratatui(Rust) make rendering far simpler.
What it taught me
The Linux kernel exposes a lot through /proc and /sys —
everything htop, ps, top, free, and uptime shows comes from
parsing these. Knowing the schema makes you faster at debugging
production issues; you can read /proc by hand instead of running
a tool. That’s been useful many times since.