How Does the Buddy Allocator Manage Memory? – Linux Device Drivers Course Online


Linux Kernel Buddy System Page Allocator Explained (Free Linux Kernel Development Course)
A beginner-friendly, hands-on lecture from EmbeddedPathashala’s Free Linux Kernel Development Course

Welcome back to EmbeddedPathashala’s free Linux kernel development course. In this lecture we open up one of the most important pieces of Linux memory management: the buddy system page allocator. If you are following our free Linux device drivers course or our free embedded systems course, this lecture gives you the memory-management foundation every kernel module and driver author needs.

We will build everything from first principles, using simple language and original explanations, and we will explain how the buddy allocator behaves on a modern, current Linux kernel — not just from a historical textbook point of view.

📘 What You Will Learn
What the buddy system page allocator is
Why physical memory is tracked in “orders”
Page migration types on a modern kernel
How node and zone freelists are organized
Pros and cons of the buddy allocator design
How to inspect freelists from user space

✅ Prerequisites

Before this lecture, you should be comfortable with:

Basic C programming
Linux command line basics
General idea of RAM and virtual memory

If any of these feel shaky, please go through the earlier lectures of this free Linux kernel development course first.

What Is the Buddy System Page Allocator?

The Linux kernel hands out physical RAM to itself and to user processes in fixed-size chunks called page frames. On most systems a page frame is 4 KB. Instead of allocating memory one byte at a time, the kernel’s lowest-level memory manager — the page allocator, often called the buddy system allocator (BSA) — hands out memory in groups of pages that are always a power of two in size.

This power-of-two grouping is called the order. An allocation of order 0 is a single page. An allocation of order 3 is 2³ = 8 contiguous pages. The buddy system keeps a separate “freelist” for every order, and whenever a block is freed, the allocator checks whether its neighbouring block (its “buddy”) is also free — if so, the two are merged back into one larger free block. This merging is what keeps physical memory from becoming permanently fragmented over time.

Order-based Freelist Concept (Inline HTML Diagram)
Order 0
1 page (4 KB)
Order 1
2 pages (8 KB)
Order 2
4 pages (16 KB)
…
Order 10
1024 pages (4 MB)

Important update for current kernels: on modern Linux (recent stable releases), the buddy allocator supports orders 0 through MAX_ORDER, and the kernel defines a constant NR_PAGE_ORDERS (currently 11) representing the total number of distinct order buckets, from order 0 up to order 10. That means the single largest physically-contiguous block the buddy system can hand out in one shot is 4 KB × 2¹⁰ = 4 MB. This is a good number to remember whenever you are sizing DMA buffers in driver code.

Why an Array of Linked Lists, Not Just One List?

A natural question beginners ask: why does the kernel keep many separate freelists instead of one big list of free pages? The answer has two parts.

Part one — per zone, per node. Physical memory on a real machine is divided into zones (for example a DMA-capable zone and a normal zone) and, on multi-socket NUMA servers, further divided by node (each CPU socket typically owns its own bank of local RAM). Every node-zone combination keeps its own independent set of freelists, because allocating “local” memory is much faster than reaching across to another node’s RAM.

Part two — page migration types. A modern kernel doesn’t just split freelists by order; it further splits each order’s freelist by migration type, so that pages with similar “movability” characteristics sit together. This grouping is the kernel’s main weapon against long-term external fragmentation.

Page Migration Types You Will See Today

On current kernels, the page allocator recognises migration types such as the following:

Migration Type Meaning
MIGRATE_UNMOVABLE Cannot be moved once allocated — kernel data structures, page tables, slab objects.
MIGRATE_MOVABLE Can be relocated freely — typical user-space process memory accessed through page tables.
MIGRATE_RECLAIMABLE Cannot be moved but can be dropped and reloaded later, e.g. some cached file-backed pages.
MIGRATE_HIGHATOMIC Reserved pool kept aside for urgent atomic (non-sleeping) high-order requests.
MIGRATE_CMA Pages managed by the Contiguous Memory Allocator, used heavily on embedded/SoC platforms for DMA buffers.
Freelist Layout per Node-Zone (Inline HTML Diagram)
Node 0 → Zone NORMAL
UNMOVABLE list
MOVABLE list
RECLAIMABLE list
HIGHATOMIC list
CMA list

…and this whole picture repeats for every order (0 to 10) and for every zone on every node.

Multiply orders × zones × nodes × migration types together and you can see how, on a real multi-socket NUMA server, the kernel ends up tracking a surprisingly large number of independent freelist structures system-wide — all to keep allocation fast and fragmentation low.

Inspecting Freelists From User Space

The kernel exposes live freelist statistics through the /proc filesystem, which is a great way to actually see the buddy allocator at work on your own machine.

cat /proc/buddyinfo

This command prints, per node and per zone, how many free blocks exist at each order. It’s a quick top-level health check of system memory fragmentation.

sudo cat /proc/pagetypeinfo

This second command (root access required) goes one level deeper and shows the same information broken down by migration type as well as order, which is exactly the detailed internal structure we discussed above.

Workflow: Reading Live Buddy Allocator State
Open terminal
→
cat /proc/buddyinfo
→
sudo cat /proc/pagetypeinfo
→
Analyse fragmentation

Pros and Cons of the Buddy System Design

Like every engineering decision, the buddy allocator design trades certain benefits against certain costs.

👍 Advantages
Keeps external fragmentation under control through buddy merging
Guarantees physically contiguous memory, required by many DMA-capable devices
Guarantees blocks are aligned, which plays nicely with CPU cache lines
Logarithmic time complexity — allocation and freeing stay fast even under load
👎 Disadvantage

The biggest weakness is internal fragmentation: because allocations are always rounded up to the next power of two, a request for, say, 5 pages is actually satisfied with an 8-page (order 3) block, wasting 3 pages. For very small allocations, the kernel instead layers the SLAB/SLUB allocator on top of the buddy system, which we will cover in a later lecture.

Common Mistakes Beginners Make

Assuming order means “number of pages” directly — remember, it is 2^order pages
Forgetting that the largest single buddy allocation is capped (order 10 by default on most configs)
Confusing migration type with allocation size
Reading /proc/pagetypeinfo without root and wondering why it’s empty

Best Practices

Prefer small orders whenever possible to reduce internal fragmentation
Use CMA-backed allocation for large DMA buffers on embedded SoCs rather than relying on order-10 buddy allocations
Monitor /proc/buddyinfo on long-running embedded systems to catch fragmentation issues early

Real-World Use Cases

Understanding the buddy allocator directly helps embedded and driver engineers in situations such as: sizing DMA-coherent buffers for network or video capture drivers, debugging “out of memory” errors that are actually fragmentation errors rather than true memory shortages, and tuning systems that run for months without reboot (routers, set-top boxes, industrial controllers) where fragmentation slowly creeps up.

Summary / Key Takeaways

The buddy system allocates physical memory in power-of-two page blocks called orders
Freelists are split by node, by zone, by order, and by migration type
Buddy merging keeps external fragmentation low
Internal fragmentation is the main trade-off
/proc/buddyinfo and /proc/pagetypeinfo let you observe this live on any Linux box

Conclusion

The buddy system page allocator is the foundation everything else in Linux memory management is built on top of — from the SLAB allocator to vmalloc to user-space page faults. Once this picture is clear in your head, the rest of the memory-management subsystem becomes far easier to reason about. In the next lecture of this free Linux kernel development course, we move from theory to practice and start using the actual page allocator APIs inside a real kernel module.

Frequently Asked Questions

Q1. What is the buddy system in the Linux kernel?
It is the low-level physical memory allocator that hands out RAM in power-of-two sized page blocks and merges freed neighbouring blocks back together to fight fragmentation.

Q2. What does “order” mean in page allocation?
Order is the exponent in 2^order pages. Order 0 is one page, order 3 is eight pages, and so on.

Q3. What is the maximum buddy allocation size on a typical kernel?
By default the maximum order is 10, giving 1024 pages — typically 4 MB on systems with a 4 KB page size.

Q4. Why are freelists split by migration type?
Grouping pages of similar “movability” together helps the kernel compact memory and avoid long-term external fragmentation.

Q5. How can I see buddy allocator statistics on my own Linux machine?
Run cat /proc/buddyinfo for a summary, or sudo cat /proc/pagetypeinfo for a detailed, migration-type-aware view.

Q6. What is the difference between internal and external fragmentation?
External fragmentation means free memory exists but is too scattered to satisfy a large request. Internal fragmentation means memory is allocated but a portion of it is wasted because of power-of-two rounding.

Q7. Is the buddy allocator used directly by application developers?
No, application developers use malloc()/free() in user space. The buddy allocator works underneath the kernel, and is directly used by kernel module and driver developers through APIs we cover in the next lecture.

Continue Your Free Linux Kernel Development Journey

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

Browse All Free Courses
Join the Community

Leave a Reply

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