Skip to content

Day 92 - kmalloc() Internals

Objective

Implement a simplified Linux-style kmalloc() frontend and understand how allocation requests are routed through predefined kmalloc caches, the SLUB allocator, and the Buddy Allocator.

Learning Goals

After completing this lab, you should understand:

  • Why Linux provides kmalloc() instead of exposing kmem_cache directly.
  • How allocation sizes are mapped to predefined kmalloc caches.
  • How kmalloc() interacts with the SLUB allocator.
  • How SLUB obtains backing pages from the Buddy Allocator.
  • The purpose of kzalloc() and kcalloc().
  • The difference between GFP_KERNEL and GFP_ATOMIC.

Lab Architecture

Application / Driver
kmalloc()
kzalloc()
kcalloc()
kfree()
kmalloc Cache Lookup
kmem_cache_alloc()
kmem_cache_free()
SLUB Allocator
Buddy Allocator
Physical Pages

Lab 1 - kmalloc Cache Lookup

Objective

Verify that allocation requests are routed to the nearest predefined kmalloc cache.

Implementation

Implemented:

  • kmalloc cache manager
  • Fixed-size kmalloc cache table
  • Cache lookup by allocation size

Example cache table:

Request Size Selected Cache
5 kmalloc-8
16 kmalloc-16
17 kmalloc-32
100 kmalloc-128

Expected Result

Example output:

[KMALLOC] size=5 -> kmalloc-8
[KMALLOC] size=16 -> kmalloc-16
[KMALLOC] size=17 -> kmalloc-32
[KMALLOC] size=100 -> kmalloc-128

The allocator should select the smallest cache capable of satisfying the requested allocation size.


Lab 2 - Slab Reuse Within the Same Cache

Objective

Verify that multiple allocation requests belonging to the same size class reuse the same kmalloc cache and slab.

Implementation

Allocate several objects:

kmalloc(20)
kmalloc(24)
kmalloc(31)

All requests should be routed to:

kmalloc-32

Expected Result

The dump should show:

[CACHE] kmalloc-32:
used = 3
slabs = 1

demonstrating that different allocation sizes can share the same slab when they belong to the same size class.


Lab 3 - Object Reuse After kfree()

Objective

Verify that freed objects are reused by subsequent allocations.

Implementation

Perform the following sequence:

Allocate:
p1
p2
p3


kfree(p2)


Allocate p4

Expected Result

p4 should reuse the memory previously owned by p2.

Example:

p2 == p4

The bitmap should mark the object as free after kfree() and allocate the lowest-index available object during the next allocation.


Lab 4 - kzalloc() and kcalloc()

Objective

Validate zero-initialized allocation.

Implementation

kzalloc()

  1. Allocate memory with kmalloc().
  2. Fill the object with a known pattern.
  3. Free the object.
  4. Allocate again using kzalloc().

kcalloc()

Allocate an array using:

kcalloc(4, 8, GFP_KERNEL);

Also verify integer-overflow protection.

Expected Result

The reused object should contain only zero bytes after kzalloc().

kcalloc() should:

  • Return zero-initialized memory.
  • Detect multiplication overflow.
  • Return NULL on overflow.

Lab 5 - GFP Allocation Policy

Objective

Validate allocation rules under different execution contexts.

Implementation

Verify the following combinations:

Context GFP Flag Expected
Process Context GFP_KERNEL Success
IRQ Context GFP_KERNEL Fail
IRQ Context GFP_ATOMIC Success

Expected Result

Example:

PROCESS_CONTEXT + GFP_KERNEL
PASS

IRQ_CONTEXT + GFP_KERNEL
PASS

IRQ_CONTEXT + GFP_ATOMIC
PASS

This demonstrates that sleeping allocations are not permitted in interrupt context.


Summary

This lab completed the simplified Linux kernel allocation path.

kmalloc()
kmalloc cache lookup
kmem_cache_alloc()
SLUB Allocator
Buddy Allocator
Physical Pages

The implementation now models the overall Linux memory allocation architecture, with kmalloc() acting as the public allocation interface while SLUB and the Buddy Allocator remain internal implementation layers.