The Linux kernel manages memory using pages, which are fixed size blocks of memory.
Each physical page is represented by a structure called struct page.
Important information stored in this structure includes:
The reference count indicates how many components are currently using the page.
Physical memory is divided into zones to handle hardware limitations.
Some devices can only access certain memory ranges, especially when using DMA.
Common zones:
| Zone | Description | Physical Memory |
|---|---|---|
ZONE_DMA |
DMA-able pages. | < 16 MB |
ZONE_NORMAL |
Normally addressable pages. | 16–896 MB |
ZONE_HIGHMEM |
Dynamically mapped pages. | > 896 MB |
During allocation, the kernel selects pages from the appropriate zone.
The main function used for page allocation is:
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order);
order determines the number of contiguous pages requested.Example:
To free pages:
void __free_pages(struct page *page, unsigned int order);
kmalloc() allocates memory inside the kernel similar to malloc().
Characteristics:
Example:
void *ptr = kmalloc(size, GFP_KERNEL);
Memory is released using:
kfree(ptr);
vmalloc() allocates virtually contiguous memory.
Unlike kmalloc, the memory does not need to be physically contiguous.
This is useful for large memory allocations when contiguous physical memory is not available.
Memory allocation functions take GFP flags that control allocation behavior.
Common flags:
| Flag | Meaning |
|---|---|
GFP_KERNEL |
normal allocation that may sleep |
GFP_ATOMIC |
allocation cannot sleep, used in interrupt context |
GFP_USER |
memory allocated for user processes |
GFP_DMA |
allocation from DMA capable memory |
GFP_KERNEL is the most commonly used flag.
The slab allocator is used to efficiently allocate frequently used kernel objects.
Instead of allocating memory every time, the kernel maintains object caches.
Structure:
Cache → Slabs → Objects
This approach improves performance and reduces memory fragmentation.
Some systems contain high memory, which is not permanently mapped in kernel space.
To access such memory, the kernel temporarily maps it using:
kmap()
The mapping is removed using:
kunmap()
This allows the kernel to access high memory when needed.