How Does kmem_cache_create() Work in Linux? – Free Linux Device Drivers Course in Hyderabad

Custom Slab Cache in Linux Kernel: A Beginner-Friendly SLUB Tutorial
Learn how kernel modules and device drivers create their own fast, reusable memory pools using kmem_cache_create() on modern kernels
Kernel Version
6.8+
Allocator
SLUB only
Difficulty
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

Why drivers create custom slab caches
The modern kmem_cache_create() API
Allocating and freeing cached objects
Destroying a cache safely
Debugging slab memory with SLUB

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.

Object Caching vs Plain kmalloc()
Driver requests object
→
Dedicated slab cache
→
Object reused, not rebuilt
→
Freed back to same 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.
Note: The actual memory handed to you can be slightly larger than what you asked for, because the allocator rounds up to the nearest size class and reserves a little space for internal bookkeeping. If you ever need to know the true usable size, call 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);
Full Life Cycle of a Custom Slab Cache
kmem_cache_create()
→
kmem_cache_alloc()
→
use object
→
kmem_cache_free()
→
kmem_cache_destroy()

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=FZPU to 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.

Key Takeaways
Custom slab caches speed up repeated allocation of one fixed-size object
SLUB is the only allocator since kernel 6.8; SLAB and SLOB are gone
kmem_cache_create/alloc/free/destroy is the complete life cycle
Use slub_debug and /sys/kernel/slab for debugging

Frequently Asked Questions

Q1. Is the SLAB allocator still available in any current Linux kernel?

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.

Q2. When should I create a custom slab cache instead of just using kmalloc()?

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.

Q3. What happens if I forget to call kmem_cache_destroy()?

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.

Q4. Can two kernel modules share the same slab cache?

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.

Q5. Is kmem_cache_alloc() safe to call from an interrupt handler?

Yes, as long as you pass GFP_ATOMIC instead of GFP_KERNEL, so the allocator knows it must not sleep while searching for memory.

Q6. How do I see how much memory my custom cache is using?

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.

Continue Your Free Linux Kernel Development Course

This lesson is part of EmbeddedPathashala’s free Linux kernel development course covering memory management, device drivers, and embedded systems from scratch.

Leave a Reply

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