Skip to content

Kernel Memory Allocation

Purpose

Linux kernel drivers use dynamic memory allocation to manage driver-private data, runtime buffers, lookup tables, and temporary objects.

Unlike userspace memory allocation, kernel allocation APIs require an allocation policy (GFP flags) that depends on the current execution context.


Common APIs

kmalloc()

void *kmalloc(size_t size, gfp_t flags);

Allocates physically contiguous kernel memory.

kmalloc() automatically selects the smallest predefined kmalloc cache capable of satisfying the requested allocation size. The allocation request is then forwarded to the SLUB allocator.

Typical usage:

  • Driver private data
  • Runtime buffers
  • Small to medium-sized allocations

kzalloc()

void *kzalloc(size_t size, gfp_t flags);

Allocates physically contiguous kernel memory and initializes all bytes to zero.

Internally, kzalloc() performs a kmalloc() allocation before clearing the allocated memory.

Typical usage:

  • Driver objects
  • Private structures
  • State containers

kcalloc()

void *kcalloc(size_t n, size_t size, gfp_t flags);

Allocates a zero-initialized array and performs integer overflow checking before calculating the total allocation size.

Internally, kcalloc() allocates memory through kmalloc(), performs integer-overflow checking, and zero-initializes the allocated memory.

Typical usage:

  • Arrays of structures
  • Descriptor tables
  • Object arrays

kfree()

void kfree(const void *ptr);

Releases memory previously allocated by the kernel allocator.

Passing NULL is safe.


vmalloc()

void *vmalloc(unsigned long size);

Allocates virtually contiguous memory.

Unlike kmalloc(), the returned virtual address may map to non-contiguous physical pages.

Typical usage:

  • Large software buffers
  • Large lookup tables
  • Kernel data structures that do not require physically contiguous memory

GFP Allocation Flags

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

Allocation Path

The simplified allocation path implemented in the labs is:

kmalloc()
kmalloc Cache Lookup
kmem_cache_alloc()
SLUB Allocator
Buddy Allocator

kmalloc() serves as the public allocation interface, while the SLUB allocator manages fixed-size objects and the Buddy Allocator supplies page-backed slab memory.


API Selection

Requirement Recommended API
Driver object kzalloc()
Generic allocation kmalloc()
Array allocation kcalloc()
Large allocation vmalloc()
Release memory kfree()

kmalloc() vs vmalloc()

Feature kmalloc() vmalloc()
Virtual Address Contiguous Contiguous
Physical Address Contiguous Non-contiguous
Allocation Speed Fast Slower
Large Allocation Limited Better
DMA Friendly Yes Generally No

GFP Selection

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

Common Mistakes

  • Using GFP_KERNEL inside an IRQ handler.
  • Allocating arrays with kzalloc(n * size) instead of kcalloc().
  • Using vmalloc() for small driver objects.
  • Forgetting to release allocated memory with kfree().
  • Performing unnecessary memory allocation inside interrupt handlers.