What is the Slab Allocator?
Learn what the slab allocator is, how it caches pre-initialized objects on top of the buddy allocator, and why it is so fast.
Expected Interview Answer
The slab allocator is a kernel memory allocator that caches pre-initialized, fixed-size objects (like task structs or inodes) in contiguous slabs carved from buddy-allocated pages, so the kernel can allocate and free frequently used objects without repeated construction cost or fragmentation.
Rather than allocating raw pages for every small kernel object, the slab allocator creates a cache per object type, and each cache is backed by one or more slabs — physically contiguous pages divided into equal-sized object slots. When an object is freed, the slab allocator does not destroy it; it keeps the object’s constructor-initialized state intact and simply returns the slot to the cache’s free list, so the next allocation of that type skips re-initialization entirely. Slabs are tracked as full, partial, or empty, and allocation is satisfied first from partial slabs to keep empty slabs available for reclaiming back to the buddy allocator under memory pressure. Because object sizes exactly match the cache’s slot size, the slab allocator eliminates the internal fragmentation the buddy system would otherwise cause for small, frequently allocated, fixed-size structures, and its per-CPU object caches (magazines) make allocation and free extremely fast with minimal locking.
- Avoids repeated constructor/destructor cost for frequently reused kernel objects
- Eliminates internal fragmentation for fixed-size objects, unlike raw buddy allocation
- Per-CPU caching reduces lock contention on hot allocation paths
- Tracks full/partial/empty slabs to reclaim memory back to the buddy allocator
AI Mentor Explanation
The slab allocator is like a kit room that keeps pre-strapped pads and pre-taped bats ready to hand out, rather than assembling a fresh set from scratch every time a batter walks in. When a batter returns their gear, the kit room does not disassemble it — it just puts the same ready-to-use set back on the shelf for the next batter of that exact size. This means handing out gear is nearly instant compared to a system that has to lace pads and tape bats fresh every single time.
Step-by-Step Explanation
Step 1
Cache creation
A cache is created per object type, defining object size and optional constructor/destructor.
Step 2
Slab backing
The cache requests pages from the buddy allocator and divides them into equal-sized object slots forming a slab.
Step 3
Allocate
An object is handed out from a partial or empty slab’s free list, skipping re-initialization if a constructor already ran.
Step 4
Free and reclaim
A freed object returns to the slab’s free list; fully empty slabs can later be reclaimed back to the buddy allocator.
What Interviewer Expects
- Understanding that slabs hold pre-initialized, fixed-size objects, not raw memory
- Why the slab allocator sits on top of, not instead of, the buddy allocator
- The full/partial/empty slab tracking model
- Per-CPU caching (magazines) as a performance optimization
Common Mistakes
- Confusing the slab allocator with the buddy system itself
- Thinking freed slab objects are always destroyed immediately
- Not knowing slabs are backed by buddy-allocated contiguous pages
- Ignoring per-CPU caching as the reason slab allocation is so fast
Best Answer (HR Friendly)
“The slab allocator keeps ready-made pools of common kernel objects, like process structures, pre-built and pre-initialized, so the kernel does not have to construct one from scratch every single time it is needed. When an object is freed, it goes back into the pool mostly intact rather than being torn down, which makes allocation and freeing extremely fast and avoids wasting memory on objects of odd sizes.”
Code Example
struct kmem_cache {
size_t obj_size;
void (*ctor)(void *obj);
struct slab *partial, *empty, *full;
};
void *cache_alloc(struct kmem_cache *cache) {
struct slab *s = cache->partial ? cache->partial : cache->empty;
if (!s) s = grow_cache_with_new_slab(cache); /* get pages from buddy allocator */
void *obj = pop_free_object(s); /* already constructed if reused */
if (s->free_count == 0) move_slab(cache, s, &cache->full);
return obj;
}
void cache_free(struct kmem_cache *cache, struct slab *s, void *obj) {
push_free_object(s, obj); /* object state kept intact */
if (slab_is_now_empty(s)) move_slab(cache, s, &cache->empty);
}Follow-up Questions
- How does the slab allocator reduce fragmentation compared to raw buddy allocation?
- What is a per-CPU slab cache (magazine) and why does it help performance?
- When does the kernel reclaim empty slabs back to the buddy allocator?
- What is the difference between SLAB, SLUB, and SLOB allocators in Linux?
MCQ Practice
1. What does a slab primarily store?
A slab is divided into equal-sized slots holding objects of one specific kernel type, often kept pre-initialized between uses.
2. What allocator typically supplies the underlying pages for a slab?
Slabs are physically contiguous pages obtained from the buddy allocator and then subdivided into fixed-size object slots.
3. Why is slab allocation often faster than plain page allocation for kernel objects?
Reusing already-constructed objects and using per-CPU magazines avoids both re-initialization cost and lock contention on hot paths.
Flash Cards
What is the slab allocator? — A kernel allocator that caches pre-initialized, fixed-size objects in slabs backed by buddy-allocated pages.
What are the three slab states? — Full, partial, and empty, tracked per cache for allocation and reclamation.
Why is slab allocation fast? — It reuses pre-constructed objects and uses per-CPU caches to minimize locking.
What sits underneath the slab allocator? — The buddy allocator, which supplies the contiguous pages a slab is carved from.