How Does /proc/buddyinfo Help Debug kmalloc()? – Free Linux Device Drivers Course in Hyderabad

Testing the kmalloc Maximum Allocation Size with a Custom Kernel Module

Free Linux Device Drivers Course • Free Linux Kernel Development Course • Free Embedded Systems Course — EmbeddedPathashala

Level
Intermediate
Reading Time
13 min
Hands-on
Kernel Module + dmesg
Category
Memory Management

test kmalloc limit kernel module
proc buddyinfo
free Linux device drivers course
free Linux kernel development course
free embedded systems course
kernel module debugging

What You Will Learn

  • How to write a small, original loadable kernel module to test kmalloc limit behaviour empirically
  • How to read the kernel log correctly when an allocation deliberately fails
  • How to interpret /proc/buddyinfo to understand real-time memory fragmentation
  • Why the exact same test can give different results on a freshly booted system vs. a long-running one

Prerequisites

  • Completion of the previous lecture on kmalloc theory (slab and buddy allocator basics)
  • A Linux VM or SBC (Raspberry Pi class board) where you can safely build and load test modules
  • Basic familiarity with make, insmod, rmmod, and dmesg

Why Test Empirically Instead of Trusting a Number

In the previous lecture we established that the kmalloc maximum allocation size depends on page size, kernel
configuration, and architecture. Rather than quoting a single number from a book or blog post, the reliable
way to test the kmalloc limit is to write a tiny kernel module that increases its request
size step by step and simply observes where it starts failing on your own target hardware and kernel build.

Building an Original Test Module

The module below is deliberately minimal. It walks through a set of allocation sizes on load, logs the
result of each attempt, frees whatever succeeded, and reports the point of failure. Build it fresh for your
own experiments rather than reusing anyone else’s binary or sample.

// ep_kmalloc_probe.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>

#define EP_STEP_BYTES   (256 * 1024)   /* 256 KB steps */
#define EP_MAX_STEPS    64             /* upper bound on iterations */

static int __init ep_kmalloc_probe_init(void)
{
	size_t req_size = 0;
	void *ptr = NULL;
	int i;

	pr_info("ep_kmalloc_probe: starting allocation sweep\n");

	for (i = 0; i < EP_MAX_STEPS; i++) {
		req_size = (size_t)i * EP_STEP_BYTES;

		ptr = kmalloc(req_size, GFP_KERNEL);
		if (!ptr) {
			pr_info("ep_kmalloc_probe: FAILED at request size = %zu bytes\n",
				req_size);
			break;
		}

		pr_info("ep_kmalloc_probe: OK   request size = %zu bytes (ptr=%p)\n",
			req_size, ptr);
		kfree(ptr);
	}

	pr_info("ep_kmalloc_probe: sweep complete\n");
	return 0;
}

static void __exit ep_kmalloc_probe_exit(void)
{
	pr_info("ep_kmalloc_probe: unloaded\n");
}

module_init(ep_kmalloc_probe_init);
module_exit(ep_kmalloc_probe_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("EmbeddedPathashala: empirical kmalloc limit probe");

A minimal Makefile to build it against your running kernel headers:

obj-m += ep_kmalloc_probe.o

KDIR := /lib/modules/$(shell uname -r)/build

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

Build, load, and observe the log:

$ make
$ sudo insmod ep_kmalloc_probe.ko
$ dmesg | tail -n 20
$ sudo rmmod ep_kmalloc_probe
Note: A single-allocation failure inside the kernel can trigger a diagnostic warning
(stack trace) in the log even though the module itself handles the NULL return correctly. That
warning is informational, not a crash — read it as “the allocator hit its limit,” not as a bug in your
module.

Interpreting the Allocation Sweep

Typical Sweep Outcome (Illustrative, Not a Fixed Rule)
256 KB ✓
512 KB ✓
1 MB ✓
2 MB ✓
3–4 MB ✓ (borderline)
Beyond ceiling ✗

Your own numbers will differ from this illustration. What matters is the pattern: allocations succeed
smoothly up to a point, then fail consistently once the request size crosses the effective
kmalloc maximum allocation size for your kernel build.

Cross-Checking with /proc/buddyinfo

The kernel exposes live buddy allocator state through /proc/buddyinfo. Each column represents
a page order, and each number is the count of free contiguous blocks currently available at that order.

$ cat /proc/buddyinfo
Node 0, zone   DMA32    120   85   40   22   10    4    2    1    0    0    0

Reading left to right, the first column is order 0 (single free pages), and the last column is the highest
order the system tracks. A zero in the highest-order column means there are currently no free blocks large
enough to satisfy an allocation at that order — which is exactly the kind of fragmentation that causes
a large kmalloc() to fail on a long-running system even though the same request succeeded right
after boot.

System State Expected High-Order Free Blocks Large kmalloc Success Likelihood
Freshly booted Plentiful High
Up for days, under load Scarce or zero Low, unpredictable

Common Mistakes

  • Testing once and treating the result as gospel. Re-run the sweep after the system has
    been up for a while; the numbers will likely shift.
  • Forgetting to free successful allocations inside the loop. This artificially exhausts
    memory and skews later iterations.
  • Ignoring architecture differences. The same module can report different ceilings on an
    x86_64 VM versus an ARM64 SBC.

Best Practices

  • Always unload test modules after use; don’t leave probe code in production builds
  • Run the sweep both right after boot and under normal workload to see the realistic range
  • Combine dmesg output with /proc/buddyinfo for a complete picture
  • Prefer kvmalloc() in real drivers once you understand where the practical ceiling lies

Troubleshooting Tips

  • If insmod fails immediately, check dmesg for a version-mismatch or missing
    symbol error before assuming the allocation logic is at fault
  • If every allocation in the sweep fails, verify you are passing a sane GFP_KERNEL flag and
    that the requested step size calculation isn’t overflowing
  • If results look inconsistent across runs, check overall system memory pressure with free -h
    before repeating the test

Summary / Key Takeaways

  • A small, original kernel module that sweeps allocation sizes is the most reliable way to test the
    kmalloc limit on your own hardware and kernel build
  • /proc/buddyinfo explains why the same request can succeed today and fail next
    week — it’s a fragmentation snapshot, not a fixed ceiling
  • Treat any single measured number as a data point for your specific system, not a universal constant

Conclusion

Pairing a hands-on probe module with /proc/buddyinfo turns the abstract idea of a kmalloc
ceiling into something you can measure, reproduce, and reason about on real hardware. This kind of
first-principles verification habit is exactly what separates driver engineers who can debug obscure
allocation failures from those who get stuck guessing. Carry this same “measure, don’t assume” approach
into the next lectures of this free Linux kernel development course.

Frequently Asked Questions

Q1. How do I test the kmalloc limit on my own board?
Build and load a small kernel module that increases its request size step by step, freeing memory after each
successful call, and watch dmesg for the point where allocation starts failing.

Q2. What does /proc/buddyinfo actually show?
It shows, per memory zone, how many free contiguous blocks exist at each page order, from single pages up to
the highest tracked order.

Q3. Why did my large kmalloc succeed once and fail later?
Physical memory fragmentation increases with system uptime and workload, reducing the number of large
contiguous free blocks available to the buddy allocator.

Q4. Is it safe to run an allocation-sweeping module on a production system?
No. Run this kind of probe only on a test VM, development board, or lab system, and always unload it after
use.

Q5. What should I check first if insmod fails?
Check dmesg for kernel version mismatches or missing symbols before assuming a logic error in the
module itself.

Q6. Does the result differ between a Raspberry Pi and a PC?
Yes, results can differ due to page size, memory zone layout, and kernel configuration differences between
architectures.

Continue the Free Linux Device Drivers Course

This lecture is part of EmbeddedPathashala’s free Linux kernel development and device drivers course.

Browse All Lectures
Subscribe for Updates

Leave a Reply

Your email address will not be published. Required fields are marked *