Skip to content

Slab Allocator

The slab allocator is a critical component of the Linux kernel's memory management system, designed to optimize memory allocation for frequently created and destroyed kernel objects. Unlike general-purpose allocators like kmalloc, the slab allocator specializes in managing small, fixed-size objects, reducing fragmentation and improving performance by organizing memory into caches. This makes it essential for kernel modules that require efficient, low-latency memory management for objects such as file descriptors, network sockets, or device drivers.


Core Concepts and Structure

The slab allocator organizes memory into caches, each dedicated to a specific object type. A cache contains one or more slabs—blocks of memory pre-allocated for the object. Each slab is divided into objects, which are either fully allocated, partially filled, or completely empty. The kernel manages these slabs dynamically, ensuring efficient reuse of memory.

Key Components

  • kmem_cache: A structure representing a cache, containing metadata like object size, slab list, and allocation strategies.
  • Slab States:
  • Empty: All objects are free.
  • Partial: Some objects are in use.
  • Full: All objects are allocated.
  • Slab Types:
  • Single: A slab contains exactly one object (used for large objects).
  • Double: A slab contains two objects (for objects that require alignment).
  • General: A slab contains multiple objects (default for most use cases).

How the Slab Allocator Works

When a kernel module requests memory for an object, the slab allocator follows these steps: 1. Cache Lookup: The module identifies the appropriate cache for the object type. 2. Slab Selection: The allocator selects a slab from the cache's list, prioritizing slabs with available objects. 3. Allocation: - If a slab has free objects, one is allocated and marked as in use. - If no free objects exist, a new slab is created (or an existing one is split if necessary). 4. Deallocation: When an object is freed, it is returned to the slab, which may be merged with neighboring slabs if they are empty.

This process minimizes the overhead of memory management and ensures that frequently used objects are allocated quickly.


Benefits and Use Cases

  • Reduced Fragmentation: By grouping objects into slabs, the allocator avoids fragmentation common in general-purpose allocators.
  • Faster Allocation: Pre-allocated slabs reduce the time needed to find and allocate memory.
  • Cache Efficiency: Slab caches align with CPU cache lines, improving access performance for frequently used objects.
  • Use Cases: Ideal for objects like struct file, struct inode, or device-specific structures that are created and destroyed frequently.

Example: Creating and Using a Slab Cache

#include <linux/slab.h>

// Define a structure for the object
struct my_object {
    int data;
};

// Initialize a cache
struct kmem_cache *my_cache;

// Module initialization
int __init my_module_init(void) {
    // Create a cache for struct my_object
    my_cache = kmem_cache_create("my_cache", sizeof(struct my_object), 0, SLAB_HWCACHE_ALIGN, NULL);
    if (!my_cache) {
        printk(KERN_ERR "Failed to create cache\n");
        return -ENOMEM;
    }

    // Allocate an object
    struct my_object *obj = kmem_cache_alloc(my_cache, GFP_KERNEL);
    if (!obj) {
        printk(KERN_ERR "Failed to allocate object\n");
        kmem_cache_destroy(my_cache);
        return -ENOMEM;
    }

    obj->data = 42;
    printk(KERN_INFO "Allocated object with data: %d\n", obj->data);

    // Free the object
    kmem_cache_free(my_cache, obj);

    return 0;
}

// Module cleanup
void __exit my_module_exit(void) {
    kmem_cache_destroy(my_cache);
}

This example demonstrates how to create a slab cache, allocate an object, and free it. The kmem_cache_create function initializes the cache, while kmem_cache_alloc and kmem_cache_free handle object lifecycle management.


Key takeaways

  • The slab allocator optimizes memory for frequent kernel object allocations by reducing fragmentation and improving cache efficiency.
  • Caches organize memory into slabs, which are managed dynamically to ensure fast allocation and reuse.
  • Slab caches are essential for kernel modules requiring low-latency memory management for fixed-size objects.
  • Proper use of slab allocators ensures robust, efficient memory handling in kernel-space applications.