Stage 3 · Build
Linux Kernel Internals
Memory Management
Virtual memory, page tables, slab allocator, and the OOM killer — how Linux manages RAM.
Virtual Memory
Every process gets its own virtual address space — a contiguous range of addresses that the kernel maps to physical RAM, swap, or memory-mapped files. This gives each process the illusion of having the entire machine to itself, and provides isolation between processes.
# Memory map of a process
cat /proc/self/maps | head -10
# 55a1f2e00000-55a1f2e01000 r-xp 00000000 08:01 12345 /usr/bin/cat
# 55a1f3000000-55a1f3022000 rw-p 00000000 00:00 0 [heap]
# Detailed memory statistics for a process
cat /proc/self/status | grep -i vm
# VmPeak: 10240 kB (peak virtual memory)
# VmSize: 8192 kB (current virtual memory)
# VmRSS: 2048 kB (resident physical memory)
# VmSwap: 0 kB (swapped out)VmRSS shows how much physical RAM the process actually uses. VmSize includes memory-mapped files and shared libraries that may not be resident.
Page Tables
The kernel maintains multi-level page tables that translate virtual addresses to physical addresses. On x86_64, this is a 4-level structure (PGD, PUD, PMD, PTE) with 4 KB pages. Each translation requires up to 4 memory lookups, so the TLB (Translation Lookaside Buffer) caches recent translations.
# System-wide page table statistics
cat /proc/vmstat | grep pgtable
# nr_pte 48321
# nr_pmd 2345
# TLB flush statistics
cat /proc/vmstat | grep tlb
# nr_tlb_local_flush 12345
# Check page size
getconf PAGE_SIZE
# 4096Large pages (2 MB or 1 GB) reduce TLB misses by covering more memory per entry. This improves performance for applications with large memory footprints like databases.
Configure Transparent Huge Pages (THP) or static huge pages for memory-intensive workloads. Check with cat /sys/kernel/mm/transparent_hugepage/enabled. Disable THP for latency-sensitive databases like Redis.
Memory Zones
Physical memory is divided into zones based on address ranges and hardware constraints. DMA zone is for devices that can only address low memory, DMA32 for devices limited to 4 GB, and Normal for everything else.
cat /proc/zoneinfo | head -30
# Node 0, zone DMA
# pages free 3456
# min 128
# low 256
# high 384
# spanned 4096
# present 3998The kernel tries to keep pages in the Normal zone. When Normal zone memory runs low, the kernel triggers direct reclaim or the OOM killer.
Slab Allocator
The kernel frequently allocates small objects (task_structs, inodes, dentries). The slab allocator pre-allocates pools of these objects to avoid expensive page-level allocations. It maintains three caches: slab (legacy), slub (default on most kernels), and slob (embedded).
# Top slab consumers by memory
slabtop -o -s c | head -20
# Or read directly
cat /proc/slabinfo | sort -nrk 3 | head -10
# dentry 123456 124000 192 21 4 : tunables ...
# inode_cache 54321 55000 608 13 4 : tunables ...
# ext4_inode_cache 12000 12500 1088 14 8 : tunables ...dentry and inode caches are usually the largest slab consumers. They grow as you access more files and shrink under memory pressure.
Swap and Page Cache
The page cache holds recently accessed file data in RAM. When memory is tight, the kernel moves anonymous pages (heap, stack) to swap space on disk. The swappiness parameter controls how aggressively the kernel swaps anonymous pages versus reclaiming page cache.
# System-wide memory overview
free -h
# total used free shared buff/cache available
# Mem: 15Gi 4.2Gi 2.1Gi 512Mi 9.1Gi 10Gi
# Swap: 2.0Gi 0B 2.0Gi
# Swappiness (0-200, default 60)
cat /proc/sys/vm/swappiness
# Check how much is actually swapped
cat /proc/meminfo | grep -E "SwapTotal|SwapFree|Cached|Buffers"A low swappiness value (10-30) is often better for desktop and interactive workloads. A higher value works well for batch processing where you want to keep the page cache warm.
OOM Killer
When the system runs critically low on memory and cannot reclaim enough, the OOM killer selects a process to terminate. It scores processes based on memory usage, runtime, and oom_score_adj, then kills the highest scorer.
# Check OOM scores for all processes
ps -eo pid,comm,oom_score --sort=-oom_score | head -10
# Adjust OOM score for a process (range: -1000 to 1000)
echo -500 > /proc/<pid>/oom_score_adj # Protect this process
echo 1000 > /proc/<pid>/oom_score_adj # Prioritize for killing
# Check if OOM killer is disabled for a process
cat /proc/<pid>/oom_score_adj
# -1000 means fully protectedProtect critical services like databases by setting a negative oom_score_adj. Set batch jobs and non-critical processes to a higher value so they are killed first.
Without tuning, the OOM killer may kill your database or application server. Always set oom_score_adj for critical services. Also consider memory limits in cgroups to prevent the OOM killer from being triggered at all.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.