Kmem Caches and Object Slabs
A kmem cache (
struct kmem_cache) is a pool dedicated to one type of object — a named factory that hands out fixed-size, fixed-alignment slots for, say,struct task_structorstruct dentry. Under the hood each cache owns a set of slabs: a slab is one or more contiguous pages obtained from the buddy allocator and carved into an integer number of equal object slots, with the free slots threaded together by an embedded free pointer that lives inside the objects themselves. This note covers the object model — howkmem_cache_create,_alloc,_free, and_destroywork, what constructors andSLAB_*flags do, how a slab is laid out, when caches get merged, and how this all relates to thekmalloc-Ncaches. Its companion The Slab Allocator and SLUB covers the allocator engine (per-CPU active slabs, partial lists,cpu_partial, debugging); read the two together. The mechanism and API described here are pinned to Linux 6.12 LTS (verified against thev6.12source tree), with 6.18 deltas noted.
Mental Model: A Cache Is a Type-Dedicated Object Pool
The cleanest way to think about a kmem cache is as a slab factory for one object type. You tell the kernel “I will allocate many objects of size S, alignment A, with this one-time constructor” at cache-creation time; thereafter every kmem_cache_alloc from that cache returns an S-byte, A-aligned slot, and kmem_cache_free returns it to the pool — never to the buddy allocator until a whole slab empties. Bonwick’s original insight (Bonwick 1994, USENIX) was that the cache, not the caller, owns the object’s construction lifecycle: expensive per-object initialization (zeroing a lock, threading a list head) runs once when the slab is carved, and freed objects are recycled in that constructed state, hot in the CPU cache.
flowchart LR KC["struct kmem_cache<br/>name, object_size, size, align, ctor, flags"] subgraph SLABS["Slabs owned by this cache"] direction TB S1["slab = 1+ pages<br/>[obj0][obj1][obj2]...[objN] + metadata"] FL["freelist: obj2 -> obj0 -> obj5 -> NULL<br/>(next-pointer embedded in each free object)"] end KC --> S1 S1 -.->|"free slots threaded by"| FL BUDDY["Buddy allocator<br/>(supplies the pages)"] BUDDY --> S1
A kmem cache and one of its slabs. What it shows: the kmem_cache descriptor records the object geometry (size, alignment, constructor, flags); each slab is a buddy-allocated run of pages divided into equal object slots; the freelist is a singly-linked list whose next pointers are stored inside the free objects, so tracking free slots costs no extra memory. The insight to take: a slab is “a page (or pages) of identical objects plus a freelist threaded through the free ones” — that single sentence is the entire data structure.
How a Slab Is Carved: struct slab, Object Slots, and the Embedded Free Pointer
A slab’s per-slab bookkeeping is the struct slab, which is overlaid on the struct page/folio of the slab’s first page (it occupies the same memory as the page descriptor — a union trick, not a separate allocation). From mm/slab.h at v6.12:
struct slab {
unsigned long __page_flags;
struct kmem_cache *slab_cache; /* which cache owns this slab */
union {
struct {
union {
struct list_head slab_list; /* node partial/full list linkage */
struct { struct slab *next; int slabs; }; /* per-CPU partial list */
};
union {
struct {
void *freelist; /* first free object in this slab */
union {
unsigned long counters;
struct {
unsigned inuse:16; /* objects in use */
unsigned objects:15; /* total objects in slab */
unsigned frozen:1; /* is this the active cpu slab? */
};
};
};
freelist_aba_t freelist_counter;
};
};
struct rcu_head rcu_head; /* for SLAB_TYPESAFE_BY_RCU deferred free */
};
unsigned int __page_type;
atomic_t __page_refcount;
};Reading the load-bearing fields: slab_cache back-points to the owning kmem_cache, so given any object’s address the kernel can find its cache (round the address down to its slab, read slab_cache). freelist is the head of this slab’s free list. inuse/objects count used vs total slots; frozen marks the slab as the per-CPU active slab (explained in The Slab Allocator and SLUB). The slab_list / {next, slabs} union is the linkage onto either a node list or a per-CPU partial list. The rcu_head overlay is used only by SLAB_TYPESAFE_BY_RCU caches to defer slab freeing by an RCU grace period.
The embedded free pointer is the crux of the layout. SLUB does not keep a separate array of “which slots are free.” Instead, each free object stores, at a per-cache fixed offset (offset in struct kmem_cache), a pointer to the next free object. So freelist points at the first free object; *(void**)(first_free + offset) is the second; and so on, until NULL. When you allocate, SLUB pops the head and follows its embedded pointer to set the new head; when you free, it writes the current head into the freed object’s free-pointer slot and makes the freed object the new head. This is why a freed object’s contents are not preserved — the allocator scribbles a pointer into it. (CONFIG_SLAB_FREELIST_HARDENED XORs that pointer with a per-cache random value to thwart exploitation; see The Slab Allocator and SLUB.)
Object geometry is computed at cache creation. The cache stores object_size (the size you asked for) and size (the size including any metadata — red zones, the free pointer when stored outside the object, padding for alignment); inuse is the offset to metadata; align the required alignment; red_left_pad the left red-zone padding when debugging. The number of objects per slab and the slab’s page order are chosen to minimize wasted space while keeping the order low (governed by slab_min_objects/slab_max_order, default max order 3; see The Slab Allocator and SLUB).
The kmem_cache API
Creating a Cache
As of the 6.x consolidation, kmem_cache_create is a _Generic macro (in include/linux/slab.h) that dispatches to either a modern args-struct form or the legacy 5-argument form, chosen by the type of the third argument:
#define kmem_cache_create(__name, __object_size, __args, ...) \
_Generic((__args), \
struct kmem_cache_args *: __kmem_cache_create_args, \
void *: __kmem_cache_default_args, \
default: __kmem_cache_create)(__name, __object_size, __args, __VA_ARGS__)The doc spells out both shapes: the new variant is kmem_cache_create(name, object_size, args, flags) where args is a struct kmem_cache_args * (or NULL for all-defaults); the legacy variant is kmem_cache_create(name, object_size, align, flags, ctor). The args struct collects the less-common parameters:
struct kmem_cache_args {
unsigned int align; /* required object alignment; 0 = none */
unsigned int useroffset; /* usercopy whitelist region offset */
unsigned int usersize; /* usercopy whitelist region size; 0 = none */
unsigned int freeptr_offset; /* custom free-pointer offset (SLAB_TYPESAFE_BY_RCU) */
bool use_freeptr_offset; /* must be true to honor freeptr_offset == 0 */
void (*ctor)(void *); /* object constructor; NULL = none */
};A concrete creation, using the convenience KMEM_CACHE macro that derives name and alignment from the struct itself:
/* from include/linux/slab.h */
#define KMEM_CACHE(__struct, __flags) \
__kmem_cache_create_args(#__struct, sizeof(struct __struct), \
&(struct kmem_cache_args) { \
.align = __alignof__(struct __struct), \
}, (__flags))
/* typical subsystem usage */
static struct kmem_cache *my_cache;
my_cache = KMEM_CACHE(my_object, SLAB_HWCACHE_ALIGN | SLAB_PANIC);#__struct stringizes the type name (it appears in /proc/slabinfo), sizeof gives object_size, and __alignof__ derives the natural alignment. kmem_cache_create “cannot be called within an interrupt, but can be interrupted” (it may sleep allocating the descriptor) — so caches are created at init time, not on hot paths.
Allocating, Freeing, Destroying
void *obj = kmem_cache_alloc(my_cache, GFP_KERNEL); /* one object, honoring GFP flags */
... use obj ...
kmem_cache_free(my_cache, obj); /* return it to the cache */
kmem_cache_destroy(my_cache); /* tear down the cache (must be empty) */kmem_cache_alloc(cache, gfp) returns one object obeying the GFP flags (e.g. GFP_KERNEL may sleep and reclaim; GFP_ATOMIC may not). In current kernels these are wrapped by allocation-profiling hooks (kmem_cache_alloc expands to alloc_hooks(kmem_cache_alloc_noprof(...))), and NUMA-aware (kmem_cache_alloc_node) and bulk (kmem_cache_alloc_bulk/kmem_cache_free_bulk) variants exist. kmem_cache_free(cache, obj) returns the object to its slab’s freelist. kmem_cache_destroy(cache) tears the cache down — it expects all objects already freed, and walks/releases the cache’s slabs; destroying a cache with live objects is a bug.
Constructors: What They Are and Why They Exist
The ctor is a function run once per object when a slab is first carved, not on every kmem_cache_alloc. This is Bonwick’s object-caching idea: the constructor establishes invariant initial state (a spinlock initialized, a list head pointing to itself, a counter zeroed) that survives free/realloc cycles. The contract, from the header: “It is the cache user’s responsibility to free objects in the same state as after calling the constructor.” That is — if your code mutates the lock or list during use, it must restore them before kmem_cache_free, because the next allocator will not see the constructor run again. Constructors are now rare in practice (most callers just memset on alloc), but they remain essential for one pattern: SLAB_TYPESAFE_BY_RCU caches, whose objects may be recycled while a lockless reader still holds a stale pointer, often use a constructor to initialize an embedded lock at slab-allocation time so that RCU readers can safely take it. Note a constructor prevents cache merging (below) and is incompatible with custom freeptr_offset.
SLAB_* Flags: Object Behavior and Alignment
The flags passed to kmem_cache_create (defined in include/linux/slab.h) tune behavior, alignment, accounting, and debugging. The ones worth knowing:
SLAB_HWCACHE_ALIGN— “Align objs on cache lines.” Pads objects to a hardware-cache-line boundary so that two objects never share a cache line (avoids false sharing between CPUs at the cost of memory). The most common alignment flag for hot, per-CPU-touched objects.SLAB_PANIC— “Panic ifkmem_cache_create()fails.” For caches the system genuinely cannot boot without.SLAB_TYPESAFE_BY_RCU— “Defer freeing slabs to RCU.” Read the header warning carefully: this delays freeing the slab page by an RCU grace period, but does not delay object freeing — a freed object may be handed back out within the same grace period. It guarantees only that the memory location stays a valid object of this type, which lets lockless lookups (rcu_read_lock; look up; revalidate key; on mismatch retry) operate safely. (Originally namedSLAB_DESTROY_BY_RCU.)SLAB_ACCOUNT— “Account to memcg.” Charges the cache’s pages to the allocating memory cgroup, so per-object kernel memory counts against container limits.SLAB_RECLAIM_ACCOUNT— marks the cache’s objects as reclaimable (e.g. caches a shrinker can free under pressure), affecting page-allocator mobility grouping and the reclaimable-memory accounting.SLAB_CACHE_DMA/SLAB_CACHE_DMA32— allocate the cache’s pages from the DMA / DMA32 zone.- Debug flags (
SLAB_RED_ZONE,SLAB_POISON,SLAB_STORE_USER,SLAB_CONSISTENCY_CHECKS,SLAB_TRACE) — usually set via theslab_debugboot parameter rather than in code; see The Slab Allocator and SLUB. SLAB_NO_MERGE— opt out of cache merging (below); the header restricts valid uses to self-tests, subsystem debug caches, and rare performance-critical caches consulted with maintainers.
Object alignment is the maximum of the requested align, the architecture minimum (ARCH_SLAB_MINALIGN, so kmem_cache_alloc pointers are suitably aligned), and any larger alignment forced by SLAB_HWCACHE_ALIGN.
Mergeable Caches
A surprise for newcomers: by default SLUB merges distinct caches that have compatible geometry into a single shared cache, to cut metadata overhead and improve cache hotness. The merge decision is find_mergeable() in mm/slab_common.c. A cache is unmergeable if slab_nomerge is set, it has a constructor (s->ctor), it has a usercopy region (usersize), or it carries any SLAB_NEVER_MERGE flag:
#define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
SLAB_FAILSLAB | SLAB_NO_MERGE)Two mergeable caches are merged when their object sizes are close (the existing cache’s size is ≥ the requested size but within sizeof(void *) of it), alignments are compatible, and they share the same SLAB_MERGE_SAME flag bits:
#define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
SLAB_CACHE_DMA32 | SLAB_ACCOUNT)The practical consequences: (1) the cache name you created may not appear in /proc/slabinfo — your objects live under a merged alias (often a kmalloc-N cache); slabinfo -a lists the merges. (2) Debug builds disable merging (the debug flags are all in SLAB_NEVER_MERGE), so a corruption that only reproduces in production but not under slab_debug may be a merging artifact — under debug each cache stands alone, changing the heap layout. Booting with slab_nomerge forces every cache separate, which is a common hardening and debugging measure.
Relationship to the kmalloc-N Caches
kmalloc is not a separate allocator — it is built on a family of general-purpose kmem caches named kmalloc-8, kmalloc-16, kmalloc-32, … one per size class. A kmalloc(n, gfp) rounds n up to the nearest size class and allocates from that class’s cache. The size classes, from kmalloc_info[] in mm/slab_common.c, are the powers of two from 8 bytes up (8, 16, 32, 64, 128, 256, 512, 1k, 2k, 4k, …) plus two filler classes, 96 and 192, that bridge the wide gaps between 64↔128 and 128↔256 to cut rounding waste. There are parallel families for different needs — kmalloc-rcl-N (reclaimable, SLAB_RECLAIM_ACCOUNT), kmalloc-cg-N (memcg-accounted), dma-kmalloc-N (DMA zone), and randomized kmalloc-rnd-NN-N caches when CONFIG_RANDOM_KMALLOC_CACHES hardening is on — indexed by enum kmalloc_cache_type. The full mechanics of size-class selection, the large-allocation fallback to the page allocator, and the ksize/kfree interface live in kmalloc and the kmalloc Caches; the key relationship to hold here is that kmalloc is “anonymous” allocation from shared size-class caches, while kmem_cache_create is “named” allocation from a dedicated cache — and because of merging, a small dedicated cache may even end up merged into a kmalloc-N cache anyway.
Failure Modes and Common Misunderstandings
- Constructor misunderstanding — assuming the
ctorruns on everykmem_cache_alloc. It runs once per object per slab carve; if you rely on it for per-allocation state you will read stale data from the previous user. Use__GFP_ZERO(orkmem_cache_zalloc) for zeroed objects. - Freeing to the wrong cache —
kmem_cache_free(cache, obj)must be given the same cacheobjcame from; the object’sslab->slab_cacheis the source of truth, and mismatches corrupt accounting. - Destroying a non-empty cache —
kmem_cache_destroyon a cache with live objects leaks and can warn/crash; all objects must be freed first. - “My cache vanished from
/proc/slabinfo” — almost always cache merging; checkslabinfo -aor bootslab_nomerge. SLAB_TYPESAFE_BY_RCUfoot-guns — treating it as “objects are RCU-freed.” It is the slab page that is RCU-delayed; objects recycle immediately, so readers must revalidate identity (the key) after acquiring a reference, exactly as the header’s worked example shows.
Alternatives and When to Choose Them
- Use a dedicated
kmem_cachewhen you allocate many objects of one type and benefit from a named cache for observability, a constructor, a usercopy whitelist, or specific alignment/RCU semantics. - Use kmalloc for ad-hoc, variably-sized small allocations where a dedicated cache would be overkill — accepting size-class rounding waste.
- Use the buddy allocator (
alloc_pages) directly for whole-page, physically-contiguous needs. - Use vmalloc for large allocations needing only virtual contiguity. The full decision tree is in kmalloc vs vmalloc.
Production Notes
Real subsystems create dedicated caches precisely for the named observability: dentry, inode_cache, task_struct, kmalloc-* are the caches that dominate /proc/slabinfo on a busy box, and watching their num_objs is the standard way to spot kernel memory growth (see The Slab Allocator and SLUB for the debug/observability tooling). The SLAB_ACCOUNT flag is what makes per-object kernel memory count toward memcg limits — important for fair container accounting, and the reason many caches that hold per-process state set it. When auditing for security, slab_nomerge plus CONFIG_RANDOM_KMALLOC_CACHES and freelist hardening are the standard knobs; merging and a deterministic freelist are conveniences that also aid heap-grooming attacks.
See Also
- The Slab Allocator and SLUB — the SLUB engine: per-CPU active slabs, partial lists,
cpu_partial, the four slab states,slab_debug,/proc/slabinfo. - kmalloc and the kmalloc Caches — the general-purpose heap of
kmalloc-Nsize-class caches built on this object model. - The Buddy Allocator — supplies the pages each slab is carved from.
- Shrinkers and Slab Reclaim — reclaiming reclaimable slab caches under memory pressure.
- GFP Flags and Allocation Contexts — the allocation-context flags
kmem_cache_allocobeys. - The Memory Cgroup memcg — what
SLAB_ACCOUNTcharges against. - MOC: Linux Memory Management MOC (§5, Slab Allocation).