Linux 9 min read

Linux Memory Management: RAM, Swap and OOM

Suresh S Suresh S
Linux Memory Management: RAM, Swap and OOM

Have you ever run the free -h command on a Linux server and panicked because it reported 90% of your RAM was “used,” yet your applications were running perfectly? Or have you hosted a memory-intensive database or local AI engine, only to have the process suddenly terminate with a cryptic “Killed” message?

The answers to these phenomena lie deep inside the Linux Memory Management subsystem. It is one of the most complex and highly optimized portions of the Linux kernel, responsible for coordinating hardware capabilities with application demands.

In 2026, with containerized microservices, virtual machines, and local LLMs demanding more memory than ever before, understanding how Linux manages RAM is a foundational skill. In this guide, we will explore the abstractions of Virtual Memory, the mechanics of paging, swap files, Zram, page caching, the inner workings of the Out-Of-Memory (OOM) Killer, and how to query memory parameters from the command line.


1. Physical RAM vs. Virtual Memory (The MMU Layer)

Operating systems do not permit user applications to write data directly to physical RAM addresses. Instead, the Linux kernel abstracts hardware memory into a layer called Virtual Memory.

    User Process (Virtual Space)           MMU / Page Table          Physical RAM (Hardware)
+----------------------------------+     +-------------------+     +-------------------------+
| [ Process A: Virtual Page 0x01 ] | ───► | Translate Address | ───► | [ Physical Page 0xA4F ] |
| [ Process B: Virtual Page 0x01 ] | ───► | Translate Address | ───► | [ Physical Page 0x2D8 ] |
+----------------------------------+     +-------------------+     +-------------------------+
*(Process A and B both use virtual address 0x01, but they map to separate physical RAM sectors)*

Why Use Virtual Memory?

  1. Process Isolation (Security): Every process runs inside its own virtual address space. Process A cannot see, read, or overwrite the memory allocated to Process B. If Process A attempts to access memory outside its allocated virtual space, the CPU blocks the operation and triggers a Segmentation Fault (Segfault).
  2. Continuous Memory Illusion: As physical RAM is written to and deleted, it becomes fragmented. Virtual memory allows the kernel to present a clean, contiguous block of address space to the application, even if the underlying physical blocks are scattered across different sectors of your RAM chips.
  3. Expanded Address Space: Virtual memory allows the system to allocate more memory than physically exists by leveraging hard disk storage (Swap) to hold inactive data.

The Hardware Bridge: MMU and TLB

The translation between virtual addresses and physical hardware addresses is performed at hardware speeds by the Memory Management Unit (MMU) inside your CPU, using database translation files called Page Tables. To speed up this address lookup, the CPU uses a specialized high-speed hardware cache called the Translation Lookaside Buffer (TLB).


2. Paging and Page Sizes (HugePages)

Linux divides memory into fixed-size chunks called Pages. On standard x86_64 architectures, the default page size is 4 Kilobytes (4KB).

Page Faults: Loading Data on Demand

When an application requests data, the CPU queries the MMU.

  • Minor Page Fault: The page is in physical memory, but its reference is not loaded in the process’s page table. The kernel updates the table mapping, which takes microseconds.
  • Major Page Fault: The page is not in physical RAM—it has been swapped out to the disk or is a new file that has not been read yet. The kernel must pause the process thread, read the data from the SSD, copy it into RAM, and update the page tables. This creates visible latency.

When 4KB is Too Small: HugePages

For large databases (like PostgreSQL or Oracle) or hypervisors (QEMU/KVM) managing virtual machines with hundreds of gigabytes of RAM, using 4KB pages creates massive page tables. This consumes gigabytes of RAM just to store the memory map, causing CPU cache misses as the TLB gets overloaded.

To solve this, Linux supports HugePages:

  • Standard HugePages: Configures memory pages of 2 Megabytes (2MB) or 1 Gigabyte (1GB).
  • Transparent HugePages (THP): A kernel thread that automatically groups standard 4KB pages into 2MB blocks in the background. (Note: Many databases recommend disabling THP because it can introduce latency spikes during background merging, preferring statically allocated HugePages instead).

Statically allocate 2MB HugePages in the kernel:

echo 1024 | sudo tee /proc/sys/vm/nr_hugepages

3. Caching and Buffers: Why “Free” RAM is Wasted RAM

A common source of confusion for new Linux administrators is seeing a server with almost zero “free” memory, despite running very few active processes.

               Total System RAM (e.g., 16GB)
┌───────────────────┬────────────────────────────────────────┐
│  Active Apps      │              Page Cache                │
│  (Used: 4GB)      │  (Buffers/Cached: 12GB)                │
└───────────────────┴────────────────────────────────────────┘

                    │ (If App needs memory, kernel instantly
                    │  reclaims space from Page Cache)

┌───────────────────────────────────────┬────────────────────┐
│  Active Apps                          │  Page Cache        │
│  (Used: 12GB)                         │  (Cached: 4GB)     │
└───────────────────────────────────────┴────────────────────┘

The Page Cache Mechanics

Accessing data from an SSD is thousands of times slower than reading directly from RAM. To maximize performance, Linux uses all unused memory as a Page Cache. When you read a file from the disk, the kernel stores a copy of those disk blocks in RAM. If you query that file again, the kernel serves it directly from memory.

  • Buffers: Represents raw disk block data (like filesystem metadata).
  • Cached: Represents actual file contents stored in memory.
  • Instant Reclamation: Page cache memory is marked as “available.” If an application suddenly launches and demands RAM, the kernel instantly discards the cached file blocks and hands the physical RAM to the application process.

Handling Dirty Pages

When an application writes data to the disk, the kernel writes the changes to the Page Cache first. The page is marked as Dirty because the data in RAM is now newer than the data on the storage disk.

Background kernel threads (pdflush, kwriteback) periodically wake up to write dirty pages to the disk. You can force this write manually:

# Force sync dirty pages to disk
sync

4. Swap Space & Zram (Compressed RAM Caching)

Swap is a dedicated partition or file on your SSD or HDD that acts as an overflow space when physical RAM is fully exhausted.

The Swappiness Parameter

The kernel parameter vm.swappiness controls how aggressively the system moves inactive memory pages to swap. The value ranges from 0 to 100 (default is 60).

  • Low Swappiness (e.g., 10): The kernel avoids swapping as much as possible, keeping application pages in physical RAM until memory is almost entirely exhausted. This is preferred for low-latency databases.
  • High Swappiness (e.g., 80+): The kernel aggressively swaps out idle process memory to keep the page cache as large as possible.

To check your current swappiness value:

cat /proc/sys/vm/swappiness

To temporarily change the swappiness:

sudo sysctl vm.swappiness=10

To make it permanent, add the following to /etc/sysctl.conf:

vm.swappiness=10

Zram vs. Zswap (Compressed RAM)

In 2026, writing swap directly to an SSD is discouraged for performance-critical systems because SSDs are slow compared to RAM and heavy swapping degrades SSD lifespan. Instead, Linux utilizes Zram.

Traditional Swap:
[ RAM Full ] ──► ( Slow disk write ) ──► [ Swap File on SSD ]

Zram (Compressed RAM swap):
[ RAM Full ] ──► ( LZO/Zstd Compress ) ──► [ Compressed Zram Block in RAM ]
*(Typically achieves 3:1 compression, effectively expanding RAM space)*
  • Zram: Creates a compressed block device directly in your RAM. When the system needs to swap, it compresses the data using fast algorithms (like lz4 or zstd) and stores it inside the designated RAM block. This can expand your effective memory capacity by 200% to 300% with negligible CPU overhead.
  • Zswap: A compressed cache that sits in front of a physical swap file on disk. It intercepts pages going to the disk swap, compresses them, and stores them in RAM. If the compressed RAM cache fills up, Zswap writes the oldest compressed pages to the actual disk.

5. The Out-Of-Memory (OOM) Killer & OOM Score Tuning

What happens when your physical RAM and Swap are completely full, and a process requests more memory? To prevent the system from freezing, the kernel invokes the Out-Of-Memory (OOM) Killer.

The Overcommit Concept

By default, Linux permits Memory Overcommit. The kernel allows applications to request more memory than physically exists, assuming they will not use all of it at the same time.

You can control this behavior via /proc/sys/vm/overcommit_memory:

  • 0 (Heuristic): The kernel uses heuristic checks to allow or deny obvious overcommits.
  • 1 (Always Overcommit): Applications can allocate unlimited memory virtual addresses, risking rapid OOM events.
  • 2 (Strict): The system will only allow allocations up to a calculated limit: Swap + (RAM * overcommit_ratio).

How the OOM Killer Chooses a Target

The OOM Killer assigns an OOM Score (oom_score) to every active process. The process with the highest score is terminated first.

  • The base score is determined by the percentage of system memory the process is using.
  • A multiplier is applied based on process priority (niceness) and runtime duration (younger processes are favored for termination over system daemons).

To view the OOM score of a running process (e.g., PID 1234):

cat /proc/1234/oom_score

Protecting Critical Processes

You can manually adjust the OOM score of critical services (like SSH or your database engine) to ensure they are protected from the OOM Killer. This is done by writing to oom_score_adj. The value ranges from -1000 (completely immune to OOM) to 1000 (kill immediately when memory runs low).

To protect your custom database daemon:

# Set OOM adjustment to -1000 (immune)
echo -1000 | sudo tee /proc/$(pgrep my_database_process)/oom_score_adj

In a custom systemd service file, you can define this parameter directly:

[Service]
OOMScoreAdjust=-1000

6. How to Monitor Memory in 2026

To monitor your system’s memory allocation and troubleshoot issues, use these command-line tools:

1. The free Command

The most common tool to query system memory:

free -h

Output:

               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.2Gi       2.1Gi       240Mi       9.1Gi        11Gi
Swap:          2.0Gi       120Mi       1.8Gi
  • free: RAM that is completely untouched and empty.
  • available: The estimated amount of memory available to start new applications without swapping. This includes free memory plus memory that can be reclaimed from the page cache.

2. Reading /proc/meminfo

This virtual file is the primary source of all system memory data:

cat /proc/meminfo | head -n 15

Key parameters to watch:

  • MemTotal: Total physical RAM.
  • MemFree: The sum of free pages.
  • MemAvailable: Memory available for new processes.
  • Buffers & Cached: Disk cache buffers.
  • Active / Inactive: Tracks page access frequency to determine which pages are candidates for swapping.

3. Monitoring System Slab Memory (slabtop)

The kernel allocates memory for its own internal data structures (like file descriptors, inodes, and network sockets) using the Slab Allocator. If your application uses millions of small files, the kernel’s slab memory can consume gigabytes of RAM. Use slabtop to monitor this:

sudo slabtop -o

7. Memory Tuning and Management Checklist

Follow this checklist to optimize memory usage on production servers:

  • Set vm.swappiness to 10 or lower on database servers.
  • Statically configure HugePages for virtualization hosts or large PostgreSQL clusters.
  • Configure OOMScoreAdjust=-1000 for critical services like SSH and monitoring agents.
  • Deploy Zram on low-memory systems (like edge nodes or Raspberry Pi devices).
  • Verify that system swap partitions are mounted on fast SSD storage.
  • Set up log rotation limits to prevent slab memory leaks from file descriptors.

Frequently Asked Questions (FAQs)

Q: What is the difference between “Free” and “Available” memory?
A: “Free” memory is RAM that is completely empty and unused. “Available” memory is the total amount of RAM that can be allocated to new applications, consisting of free RAM plus the portion of the page cache that can be reclaimed.

Q: Why does my application show high virtual memory usage?
A: Virtual memory usage includes all memory addresses the application has mapped, including shared libraries, memory-mapped files on disk, and allocated but unused pages. High virtual memory usage is normal and not a cause for concern as long as physical RAM usage remains stable.

Q: Can I disable Swap completely?
A: Yes, but it is not recommended. Even if you have plenty of RAM, swap acts as a safety valve. Without swap, temporary memory spikes will instantly trigger the OOM Killer, potentially terminating critical system processes.

Q: How do I clean the system page cache manually?
A: If you need to clear the cache (for benchmarking or troubleshooting disk speeds), write to drop_caches:

# Clear page cache only
echo 1 | sudo tee /proc/sys/vm/drop_caches

# Clear dentries and inodes
echo 2 | sudo tee /proc/sys/vm/drop_caches

# Clear Page Cache, dentries, and inodes
echo 3 | sudo tee /proc/sys/vm/drop_caches

(Warning: Dropping caches on a active production server will cause temporary performance degradation as the system reads files from the disk again).

Q: What is a memory leak, and how do I identify it?
A: A memory leak occurs when a program allocates memory but fails to release it back to the operating system after use. To find leaks, use Valgrind during development, or monitor the process’s resident set size (RSS) over time using ps:

ps -o pid,user,%mem,rss,cmd -ax | sort -b -k3 -r

Next Steps for Hardening Your Infrastructure:
Learn how to Configure a UFW Firewall on Linux or secure your remote host terminals with our SSH Hardening Guide.

Suresh S

Written by Suresh S

Systems Engineer & Tech Educator with 8+ years of experience in Linux Administration, Cloud Computing, and Cybersecurity. Founder of FreeTechLearner, dedicated to creating practical tutorials that help students and professionals build real-world skills.

Share this post:

Discussion

Loading comments...