Skip to main content

Command Palette

Search for a command to run...

Linux Kernel Module for Memory and Per-Process RSS via /proc

Updated
4 min read
Linux Kernel Module for Memory and Per-Process RSS via /proc

Building a Linux Kernel Module for Memory and Per-Process RSS via /proc

User-space utilities such as top, htop, and free present a polished view of system memory usage, but they abstract away substantial kernel-level mechanics. To understand how Linux actually tracks memory—both globally and per process—I implemented a Linux kernel module that exposes system-wide memory statistics and per-process Resident Set Size (RSS) directly through /proc.

The result is a minimal, educational kernel-space alternative to user-space monitoring tools, designed explicitly to reinforce core Linux kernel concepts rather than replace existing utilities.


Overview

The module registers a virtual /proc entry that reports:

  • System-wide memory statistics (total, free, used, buffers)
  • Per-process memory usage (RSS) for all user-space processes

All data is gathered inside the kernel, without relying on /proc/meminfo or /proc/[pid]/status as intermediaries.


Module Functionality

/proc Interface

The module creates a virtual proc entry:

This file does not exist on disk. Its contents are generated dynamically each time it is read.


System-Wide Memory Statistics

The kernel’s global memory state is retrieved using si_meminfo():

  • Total RAM
  • Free RAM
  • Used RAM
  • Buffer memory

These values come directly from kernel accounting structures, ensuring accuracy and eliminating any user-space interpretation.


Per-Process RSS Reporting

To report per-process memory usage, the module:

  • Iterates over all tasks using for_each_process
  • Skips kernel threads (which have no user memory context)
  • Extracts RSS using get_mm_rss(task->mm)

For each eligible process, the output includes:

  • PID
  • Process name (comm)
  • RSS in pages (or converted to kilobytes)

This mirrors how tools like top internally derive memory usage, but without leaving kernel space.


Safe and Scalable Output with seq_file

The module uses the seq_file API to emit output:

  • Supports large output safely
  • Automatically handles pagination
  • Prevents buffer overflows
  • Avoids manual offset and length tracking

This is the canonical mechanism for /proc entries that may grow beyond a single page.


Key Kernel Concepts Reinforced

Building this module clarified several core Linux internals that are often hidden by user-space abstractions.

1. Memory Accounting via mm_struct

  • RSS is tracked at the mm_struct level
  • Kernel threads do not have an mm_struct
  • User processes share memory mappings in predictable ways

Understanding this explains why some processes appear in ps but not in memory listings.


2. Dynamic Nature of /proc

  • /proc files are generated on demand
  • No persistent storage exists for their contents
  • Read operations invoke kernel callbacks

This reinforces that /proc is an interface—not a filesystem in the traditional sense.


3. Kernel Iteration Over Processes

  • for_each_process walks the global task list
  • Requires care to avoid dereferencing invalid memory
  • Must handle tasks exiting concurrently

Even read-only inspection requires disciplined kernel programming.


4. Why seq_file Is Mandatory for Real Modules

Manual string buffers are unsafe for variable-length output. The seq_file API:

  • Manages internal buffers automatically
  • Scales with process count
  • Is required for production-quality /proc modules

Debugging and Learning Challenges

Secure Boot and Kernel Lockdown

On UEFI systems with Secure Boot enabled:

  • Unsigned kernel modules are rejected—even for root
  • The kernel enforces lockdown mode

Resolution involved:

  • Generating a Machine Owner Key (MOK)
  • Signing the module using sign-file
  • Enrolling the key via mokutil

This highlighted the security model modern kernels enforce by default.


vermagic Mismatches

Several build failures were traced to:

  • Compiling against incorrect kernel headers
  • Header versions not matching the running kernel

This reinforced the importance of:

  • Matching uname -r exactly
  • Avoiding stale header packages

Kbuild and Makefile Discipline

Kernel builds exposed why:

  • Kernel Makefiles must be path-sensitive
  • Build logic should be minimal and kernel-centric
  • Project orchestration (docs, scripts, tooling) must remain outside Kbuild

Mixing human-oriented build steps with kernel build logic leads to fragile modules.


Why This Matters

User-space tools provide convenience. Kernel modules provide truth.

By implementing this module, the following became concrete rather than theoretical:

  • How Linux accounts memory internally
  • How process memory differs from system memory
  • Why certain abstractions exist in user-space tools
  • How kernel APIs prioritize safety and scalability

This project was not about performance or production deployment—it was about understanding Linux from the inside out.


Summary

This kernel module demonstrates:

  • Creating a dynamic /proc entry
  • Extracting global memory data using si_meminfo
  • Iterating safely over processes with for_each_process
  • Computing per-process RSS via mm_struct
  • Using seq_file for robust output
  • Navigating Secure Boot, module signing, and Kbuild pitfalls

For anyone serious about systems programming, kernel development, or low-level performance work, projects like this provide insight that no user-space API can fully replicate.

The complete source code for this Linux kernel module is available on GitHub Repository


If needed, this can be extended further to:

  • Filter processes by UID
  • Export data via debugfs
  • Track memory deltas over time
  • Integrate with eBPF for hybrid kernel/user analysis