How Linux Slab Allocator Manages Object Caching

The Linux slab allocator is a memory management mechanism designed to optimize kernel memory allocation by retaining pre-allocated, initialized object instances in dedicated caches. Rather than repeatedly allocating and freeing memory pages through the lower-level buddy allocator—which introduces latency and internal fragmentation—the slab allocator maintains pools of commonly requested kernel structures, such as inodes, process descriptors, and network buffers. This overview explores the architectural structure of the slab allocator, the life cycle of cached objects, and the operational mechanics that allow Linux to achieve high-performance memory utilization.

The Purpose of Object Caching

In an operating system kernel, specific data structures are created, used, and destroyed millions of times during system operation. Creating a complex kernel object typically involves two expensive operations: allocating memory space and initializing its member fields (such as locks, list pointers, and reference counters).

The buddy allocator, which is Linux's primary page allocation system, operates on chunks of memory consisting of whole pages (typically 4 KB or larger). Using the buddy system to allocate small objects—such as a 128-byte data structure—causes severe internal fragmentation and excessive page management overhead. The slab allocator sits between the buddy allocator and kernel requests, slicing full pages into fixed-size slots and keeping the underlying objects in a semi-constructed state to eliminate the need to re-initialize them on every allocation.

The Slab Allocator Hierarchy

The slab caching architecture operates across three main structural tiers:

  1. Caches (kmem_cache): Each specific type of kernel object has its own dedicated cache (for example, task_struct, mm_struct, or dentry). There are also generic caches used by kmalloc to satisfy arbitrary byte-size requests. A cache tracks allocation metrics, object sizes, constructors, and pointers to slab lists.
  2. Slabs: A slab consists of one or more physically contiguous memory pages obtained from the buddy system. These pages are divided into an array of equal-sized memory slots corresponding to the object type held by the cache.
  3. Objects: These are the individual data structures residing inside a slab. They represent the actual memory addresses returned to kernel subsystems during an allocation call.

Slab States and Tracking

To manage memory availability efficiently, slabs within a cache are organized into three primary states:

When a subsystem requests an object via kmem_cache_alloc(), the allocator searches the partial list first to satisfy the request without requesting new memory. If no partial slab exists, it uses an empty slab. If no empty slabs are available, the allocator queries the buddy system to allocate fresh physical pages and creates a new slab.

Allocation and Deallocation Mechanics

The primary optimization of the slab allocator lies in how it handles the lifecycle of an object:

If freeing an object causes a slab to transition from full to partial, the slab is moved to the partial list. If all objects within a slab become free, the slab moves to the empty list.

Memory Reclamation

To prevent kernel caches from consuming excessive amounts of RAM, the slab allocator includes a reclamation interface integrated with the kernel's memory management subsystem. During periods of low memory pressure, empty slabs remain intact to handle future allocation bursts. Under significant memory pressure, kernel shrinkers trigger the release of empty slabs, returning the underlying physical pages back to the buddy allocator for use by user-space applications or other kernel components. Modern implementations (such as the default SLUB allocator) refine this model by using per-CPU slab queues to eliminate lock contention on multiprocessor systems.