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_KERNELwhenever sleeping is permitted. - Use
GFP_ATOMIConly in non-sleepable contexts. - Avoid allocating memory inside IRQ handlers whenever possible.
- Allocate long-lived resources during
probe()and release them duringremove().