6.8+
SLUB only
Intermediate
If you are learning Linux kernel programming and you keep hearing the term slab allocator, this tutorial is for you. A custom slab cache is simply a private, pre-organized pool of memory that a kernel module reserves for one specific object, so that allocating and freeing that object is fast and predictable. This is one of the core skills taught in any serious free Linux kernel development course, and it is heavily used inside real device drivers.
What You Will Learn
Prerequisites: basic C programming, a working Linux kernel module build environment (kernel headers installed), and familiarity with kmalloc()/kfree(). If you have not covered those yet, please go through our free Linux kernel development course fundamentals first.
Why Not Just Use kmalloc() Every Time?
Picture a network driver that allocates a small “packet descriptor” structure thousands of times per second, uses it for a few microseconds, and immediately frees it. Calling the general-purpose kmalloc() allocator for this repeated pattern works, but it is not the most efficient option, because kmalloc() has to find a generic size bucket that may waste memory and does not know anything about how this particular object is normally initialised.
The kernel’s slab layer solves this by letting a module say, in effect: “Reserve me a dedicated pool sized exactly for my structure, and keep recycling the same memory blocks instead of returning them to the general pool every time.” This is object caching, and it is the entire idea behind a custom slab cache.
An Important Update: SLAB and SLOB Are Gone
Many older books and tutorials describe three slab allocator implementations inside the kernel: SLAB, SLOB, and SLUB. This is no longer accurate. The SLOB allocator (aimed at very small embedded systems) was removed in kernel 6.4, and the older SLAB implementation was deprecated and then fully removed in kernel 6.8. From that point onward, SLUB is the only slab allocator in mainline Linux. The good news for you as a learner is that the public API — kmem_cache_create(), kmem_cache_alloc(), kmem_cache_free(), kmem_cache_destroy() — stayed exactly the same, so any code you write today will keep working.
Step 1: Creating a Custom Slab Cache
Every custom cache starts with kmem_cache_create(). On current kernels this function actually accepts two calling styles: a simple legacy style with five plain arguments, and a newer style that passes an optional struct kmem_cache_args pointer for advanced settings. For everyday driver work, the simple style is still perfectly valid and is what you will see in the vast majority of kernel source files.
#include <linux/slab.h>
struct packet_desc {
u32 seq_num;
u16 length;
void *payload;
};
static struct kmem_cache *packet_cache;
static int __init mydriver_init(void)
{
packet_cache = kmem_cache_create(
"packet_desc_cache", /* name shown in /proc/slabinfo */
sizeof(struct packet_desc), /* object size */
0, /* alignment, 0 = default */
SLAB_HWCACHE_ALIGN, /* flags */
NULL); /* constructor, none here */
if (!packet_cache)
return -ENOMEM;
return 0;
}
Here is a plain-language breakdown of each argument:
| Argument | Meaning |
|---|---|
| name | A label used only for identification in tools like slabtop and /proc/slabinfo. |
| size | The exact byte size of the object you want the cache to hold, usually sizeof(your_struct). |
| align | Byte alignment requirement. Pass 0 unless you have a specific hardware reason, such as DMA constraints. |
| flags | Behavioural options such as SLAB_HWCACHE_ALIGN (cache-line alignment for performance) or SLAB_ACCOUNT (memory cgroup accounting). |
| ctor | An optional constructor function the kernel runs once when a fresh slab page is carved into objects. Pass NULL if you do not need one. |
kmem_cache_size(packet_cache).Step 2: Allocating and Freeing From the Cache
Once the cache exists, grabbing an object from it is a single call, and it is much cheaper than a fresh kmalloc() call because the memory is already carved out and ready to use.
struct packet_desc *pkt;
pkt = kmem_cache_alloc(packet_cache, GFP_KERNEL);
if (!pkt)
return -ENOMEM;
pkt->seq_num = 42;
pkt->length = 128;
/* ... use the object ... */
kmem_cache_free(packet_cache, pkt);
Notice that kmem_cache_alloc() still takes a GFP flag, exactly like kmalloc(), because the underlying page allocator rules for sleeping vs atomic context still apply. Use GFP_KERNEL in process context where sleeping is allowed, and GFP_ATOMIC inside interrupt handlers or when holding a spinlock.
Step 3: Destroying the Cache on Module Unload
A custom slab cache is a system-wide resource. If your module is removed while the cache still exists, you leak memory and confuse the slab subsystem. Always destroy it in your exit path, and only after every object has already been freed back to it.
static void __exit mydriver_exit(void)
{
kmem_cache_destroy(packet_cache);
}
module_init(mydriver_init);
module_exit(mydriver_exit);
Debugging Slab Caches on a Modern Kernel
Since SLUB is now the only allocator, all debugging is done through SLUB’s own tooling instead of separate SLAB-specific tools. The two most useful entry points for a beginner are:
- /sys/kernel/slab/<cache-name>/ — a directory of readable files showing object count, slab count, and per-cache statistics for the cache you created.
- slub_debug boot parameter — adding
slub_debug=FZPUto the kernel command line turns on sanity checks, red-zoning, poisoning, and allocation-site tracking for all caches, which is invaluable when chasing a use-after-free or buffer overrun bug.
Real-World Use Cases
Custom slab caches show up constantly in the kernel you already run. The task_struct for every process, the networking sk_buff head, filesystem inode caches, and TCP connection structures are all backed by dedicated slab caches for exactly the performance reasons described above. When you write your own driver for a device that repeatedly allocates one kind of structure — a USB request block, a packet buffer, a command descriptor — a custom cache is the professional way to do it.
Common Mistakes to Avoid
- Calling kmem_cache_destroy() while objects from that cache are still in use — this corrupts kernel memory.
- Using GFP_KERNEL inside an interrupt handler or while holding a spinlock, which can cause the kernel to sleep where it is not allowed to.
- Creating a brand-new cache for a tiny, rarely-allocated structure — if allocations are infrequent, plain kmalloc() is simpler and just as effective.
- Forgetting to check the return value of kmem_cache_create() for NULL before using the cache pointer.
Best Practices
- Only create a custom cache when the object is allocated and freed frequently and its size is fixed and known in advance.
- Use SLAB_HWCACHE_ALIGN for objects accessed on a hot code path to reduce cache-line contention on multi-core systems.
- Name your cache descriptively, since that name is what you will see in slabtop(1) and /proc/slabinfo while debugging.
- Always pair every kmem_cache_create() with a matching kmem_cache_destroy() in the module’s cleanup path.
Frequently Asked Questions
No. SLAB was deprecated starting in kernel 6.5 and completely removed in kernel 6.8. Every kernel you build or run today uses SLUB for slab-based allocation, even though the public kmem_cache_* API names have not changed.
Create one when you allocate and free the same fixed-size structure very frequently, such as inside a hot data path of a driver. For occasional or one-off allocations, kmalloc() is simpler and has no measurable downside.
The cache and any memory still associated with it remain allocated even after your module is unloaded, which is a kernel memory leak. On some kernel configurations this can also trigger a warning when the module is reloaded and tries to create a cache with the same name.
Not directly. Each call to kmem_cache_create() creates its own cache instance. However, the slab layer may internally merge caches with identical properties for efficiency, which is transparent to your module code.
Yes, as long as you pass GFP_ATOMIC instead of GFP_KERNEL, so the allocator knows it must not sleep while searching for memory.
Check /proc/slabinfo for a system-wide table, or look inside /sys/kernel/slab/<your-cache-name>/ for detailed per-cache statistics including active objects and total slabs.
This lesson is part of EmbeddedPathashala’s free Linux kernel development course covering memory management, device drivers, and embedded systems from scratch.
