The Linux kernel page allocator, also called the buddy system allocator or BSA, is the foundation of memory management inside the Linux kernel. Every time the kernel itself, a kernel module, or a device driver needs a chunk of physically contiguous RAM, it eventually ends up at this allocator. If you are following a free Linux kernel development course or a free Linux device drivers course, understanding the page allocator is a mandatory milestone before you can confidently work with DMA buffers, slab caches, or memory-mapped I/O.
In this lesson of our free embedded systems course, you will learn how the buddy system organizes free memory, how to read its live state from the kernel, and how modern kernels expose and use this allocator through stable, supported APIs.
Buddy System Allocator
Free Linux Kernel Development Course
Free Linux Device Drivers Course
Free Embedded Systems Course
What You Will Learn
- What the Linux kernel page allocator (buddy system allocator) is and why the kernel needs it
- How the buddy system freelist is organized using orders and power-of-2 chunk sizes
- How to inspect live buddy allocator state on a running system
- The kernel-space APIs used to request and release pages from the buddy allocator
- Real-world use cases, common mistakes, performance and security considerations
Prerequisites
- Basic C programming knowledge
- A Linux machine or virtual machine for hands-on practice
- Familiarity with basic Linux kernel module concepts (recommended, not mandatory)
What Is the Linux Kernel Page Allocator?
The Linux kernel manages physical RAM in fixed-size units called page frames (commonly 4 KB on x86 and ARM). Whenever any part of the kernel — the core, a loaded module, or a device driver — needs physically contiguous memory, it cannot simply call something like a user-space malloc(). Instead, it goes through the kernel’s own memory engine, and the lowest-level engine in that chain is the page allocator, implemented using an algorithm known as the buddy system.
The buddy system’s job is simple to state but clever in implementation: keep track of which page frames are free, and hand out physically contiguous blocks of pages efficiently, while minimizing wasted space (fragmentation) as much as possible.
How the Buddy System Freelist Works
The buddy allocator keeps an array of freelists, where each index in the array is called an order. Order N holds free blocks made up of 2^N contiguous page frames. This means the size of memory available on each list doubles as you move to the next order, and halves as you move to the previous one.
On most common architectures such as x86-64 and ARM64, the maximum order is 10 (an internal constant in current kernels sets the number of usable orders so that the largest single contiguous block obtainable is 210 = 1024 pages, i.e. 4 MB with a 4 KB page size). Larger systems with different page-size capabilities can support a different range, but the underlying power-of-2 freelist principle stays the same across kernel versions.
Each entry in a freelist is not the raw memory itself — it is a kernel metadata structure (struct page) that describes and points to a real block of physical RAM. Two free blocks of the same order that sit next to each other in physical memory are called buddies. When both buddies become free at the same time, the allocator merges (coalesces) them into a single free block of the next higher order. This coalescing behavior is what keeps fragmentation low over time.
Inspecting the Buddy Allocator on a Running System
Modern Linux exposes a live summary of buddy allocator state through the proc filesystem. You can check it yourself on any Linux machine:
cat /proc/buddyinfo
The output shows one row per memory zone, with a column for every order from 0 up to the architecture’s maximum order. Each number tells you how many free, physically contiguous blocks currently exist at that order. A high count at low orders combined with very low counts at high orders is a classic early sign of external fragmentation — something embedded and driver developers should keep an eye on over long-running systems.
| Order | Pages | Size (4 KB page) |
|---|---|---|
| 0 | 1 | 4 KB |
| 3 | 8 | 32 KB |
| 6 | 64 | 256 KB |
| 10 | 1024 | 4 MB |
Using the Page Allocator APIs in Kernel Code
The kernel exposes the buddy allocator to module and driver writers through a small family of allocation and free functions, declared in linux/gfp.h and linux/mm.h. The most commonly used pair in current kernels are alloc_pages() / __get_free_pages() for allocation, and __free_pages() for releasing memory back to the allocator.
#include <linux/gfp.h>
#include <linux/mm.h>
/* Allocate 2^order contiguous pages */
unsigned long addr = __get_free_pages(GFP_KERNEL, order);
if (!addr) {
/* handle allocation failure */
}
/* ... use the memory ... */
/* Release it back to the buddy allocator */
free_pages(addr, order);
The first argument, the GFP flag, tells the allocator the context and behavior expected of the request — for example, GFP_KERNEL is used for normal allocations that are allowed to sleep, while GFP_ATOMIC is used inside interrupt context where the call must not sleep. Choosing the correct GFP flag is one of the most important practical skills in kernel and driver development, and it is something every free Linux device drivers course should cover in depth.
Real-World Use Cases
Device drivers that need physically contiguous memory for DMA transfers (network cards, storage controllers, camera sensors) ultimately rely on the buddy allocator to satisfy that contiguity requirement.
The slab/SLUB allocator, used for frequent small fixed-size kernel object allocations, itself requests large pages from the buddy allocator and slices them up internally.
Large transparent and explicit huge pages are built directly on top of high-order buddy allocations.
Common Mistakes and Troubleshooting Tips
- Requesting very high orders: Large contiguous allocations frequently fail once a system has been running for a while and memory has fragmented. Prefer smaller orders or
vmalloc()-style non-contiguous allocation when physical contiguity is not strictly required. - Wrong GFP flag in atomic context: Using
GFP_KERNELinside an interrupt handler can cause the kernel to sleep where it must not, leading to crashes. Always useGFP_ATOMICin such contexts. - Forgetting to free the same order: The order passed to the free function must match the order used at allocation time, otherwise memory accounting becomes corrupted.
- Ignoring allocation failure: Always check the return value; the buddy allocator can legitimately fail to satisfy a request.
Best Practices
- Request the smallest order that satisfies your contiguity requirement.
- Use the slab allocator (
kmalloc) for small, frequently allocated objects instead of going directly to the page allocator. - Monitor
/proc/buddyinfoover the lifetime of long-running embedded systems to catch fragmentation early. - Match GFP flags to the calling context every single time.
Performance Considerations
Because the buddy allocator coalesces and splits blocks using simple bitwise and pointer operations, allocation and free operations are fast — typically O(log N) relative to the order requested. However, high-order allocations become progressively more expensive and more likely to fail as system uptime increases and fragmentation grows, which is why drivers should minimize reliance on large contiguous allocations wherever possible.
Security Considerations
Kernel memory handed out by the page allocator is never automatically zeroed unless the caller requests it (for example via __GFP_ZERO). Drivers that allocate pages destined to be shared with user space or hardware must zero or otherwise sanitize the memory before exposing it, to avoid leaking stale kernel data.
Summary / Key Takeaways
- The buddy system allocator is the lowest-level engine managing physical page frames in the Linux kernel.
- Free memory is tracked in power-of-2 sized freelists indexed by order.
/proc/buddyinfogives a live, readable view of allocator state.alloc_pages()/__get_free_pages()andfree_pages()are the standard kernel APIs for direct page allocator access.- Choosing the right order and GFP flag is essential for reliability in drivers and kernel modules.
Conclusion
The Linux kernel page allocator may sit several layers below the APIs most driver developers use day to day, but understanding the buddy system is what turns a driver writer who copies code into one who can genuinely debug memory-related failures, fragmentation issues, and DMA allocation problems. This lesson is part of our ongoing free Linux kernel development course and free Linux device drivers course at EmbeddedPathashala — continue to the next lecture to go deeper into kernel memory management.
Frequently Asked Questions
Q1. What is the buddy system algorithm in the Linux kernel?
It is the algorithm used by the Linux kernel page allocator to track and hand out physically contiguous page frames using power-of-2 sized freelists.
Q2. What is the maximum allocation size from the page allocator?
It depends on the architecture’s configured maximum order; on common x86/ARM systems with 4 KB pages, the largest single block is typically 4 MB.
Q3. How do I check buddy allocator state on my system?
Run cat /proc/buddyinfo from a terminal on any Linux machine.
Q4. What is the difference between the page allocator and the slab allocator?
The page allocator hands out whole pages (or power-of-2 groups of pages); the slab allocator sits on top of it to efficiently manage small, fixed-size kernel objects.
Q5. Can kernel memory be swapped out?
No. Kernel memory allocated through the page allocator is never swapped to disk, unlike typical user-space memory pages.
Q6. What GFP flag should I use in an interrupt handler?
Use GFP_ATOMIC, since allocation in interrupt context must never sleep.
Q7. Why would a high-order page allocation fail even with enough total free memory?
Because the allocator requires physically contiguous blocks; fragmentation can leave plenty of free memory scattered across small non-contiguous chunks.
Explore more free lessons on Linux kernel programming, Linux device drivers, and embedded systems at EmbeddedPathashala.

1 Comment