Skip to content

Kernel Memory Allocation

Purpose

Linux kernel drivers frequently require dynamic memory allocation for driver-private data, runtime buffers, lookup tables, and temporary objects.

Unlike userspace programs, kernel code must choose an appropriate allocation API and allocation policy according to the execution context.

Understanding kernel memory allocation is essential for writing safe and efficient device drivers.


Common Allocation APIs

API Description Typical Usage
kmalloc() Allocate physically contiguous memory. Driver private data, buffers
kzalloc() Allocate and zero-initialize memory. Driver objects and structures
kcalloc() Allocate a zero-initialized array with overflow checking. Arrays of objects
kfree() Release memory allocated by the kernel allocator. Resource cleanup
vmalloc() Allocate virtually contiguous memory. Large memory regions

kmalloc Allocation Path

kmalloc() is the primary kernel API for allocating small memory objects.

Instead of allocating pages directly, kmalloc() selects the smallest predefined kmalloc cache capable of satisfying the requested allocation size. The allocation request is then forwarded to the SLUB allocator.

For example:

Requested Size Selected Cache
5 bytes kmalloc-8
20 bytes kmalloc-32
100 bytes kmalloc-128

The overall allocation path is:

Driver / Kernel Subsystem
kmalloc()
kmalloc Cache Lookup
kmem_cache_alloc()
SLUB Allocator
Buddy Allocator
Physical Pages

kmalloc() acts as the public allocation interface, while the SLUB allocator manages fixed-size objects and the Buddy Allocator provides page-backed memory for new slabs.


GFP Allocation Flags

The Linux kernel uses GFP (Get Free Pages) flags to determine how memory allocation should be performed.

The allocation flag depends on whether the current execution context is allowed to sleep.

GFP Flag Sleep Allowed Typical Context
GFP_KERNEL Yes Process Context, Workqueue, kthread
GFP_ATOMIC No IRQ Context, Atomic Context

Choosing the Correct Allocation API

Requirement Recommended API
General-purpose object allocation kzalloc()
Array allocation kcalloc()
Large allocation vmalloc()
Release allocated memory kfree()

Zero-initialized Allocation

For driver objects, Linux commonly provides two helper APIs built on top of kmalloc().

API Description
kzalloc() Allocates memory using kmalloc() and initializes all bytes to zero.
kcalloc() Allocates an array of objects, performs integer-overflow checking, and zero-initializes the allocated memory.

These helpers simplify initialization and help avoid uninitialized memory bugs.


Choosing the Correct GFP Flag

Execution Context Recommended GFP Flag
Process Context GFP_KERNEL
Workqueue GFP_KERNEL
kthread GFP_KERNEL
IRQ Context GFP_ATOMIC
Holding a Spinlock GFP_ATOMIC

Typical Driver Allocation Flow

A typical platform driver performs most memory allocation during probe().

probe()
    ├── kzalloc(..., GFP_KERNEL)
    ├── request_irq()
    ├── Initialize locks
    ├── Initialize workqueue
    └── Register device

IRQ Handler
    ├── Record event
    ├── Schedule bottom half
    └── Return immediately

Workqueue
    ├── Allocate additional resources if necessary
    └── Process deferred work

remove()
    └── kfree()

Best Practices

  • Prefer kzalloc() when allocating driver objects.
  • Use kcalloc() when allocating arrays.
  • Use GFP_KERNEL whenever sleeping is permitted.
  • Use GFP_ATOMIC only in non-sleepable contexts.
  • Avoid allocating memory inside IRQ handlers whenever possible.
  • Allocate long-lived resources during probe() and release them during remove().