6.4 Virtual Memory Management

6.4 Virtual Memory Management
Linux System Programming — Chapter 6
4
Core Concepts
3
Code Examples
6
Interview Questions

What You Will Learn

Virtual memory is the technique Linux uses to give every process its own private, isolated address space — even when physical RAM is limited. Understanding virtual memory explains why processes don’t interfere with each other, how shared libraries work, and what causes a segfault.

Virtual vs Physical Memory

Each process thinks it has a large, contiguous address space all to itself. In reality the kernel uses a page table to map the process’s virtual addresses to physical RAM frames. Only the pages a process is actively using need to be in RAM — unused pages can be swapped to disk.

Virtual Address → Page Table → Physical RAM
Process A
Virtual Address Space
Virtual Page 0
Virtual Page 1
Virtual Page 2 (swapped)
Virtual Page 3
Page Table
kernel managed
→ Frame 3
→ Frame 7
→ Disk (swap)
→ Frame 1
Physical RAM
Actual hardware frames
Frame 0 (Process B)
Frame 1 (Process A pg3)
Frame 2 (Process B)
Frame 3 (Process A pg0)
Frame 4 (free)
Frame 5 (shared lib)
Frame 6 (free)
Frame 7 (Process A pg1)

Locality of Reference — Why It Works

Virtual memory is efficient because most programs exhibit locality of reference — they tend to use a small “working set” of pages repeatedly, rather than jumping all over memory.

Two Types of Locality
Spatial Locality
If you access address X, you will soon access X+1, X+2 …
Example: Iterating through an array — adjacent elements are in the same page.
Temporal Locality
If you access address X now, you will access X again soon.
Example: A loop body runs thousands of times — same code pages reused.

Pages, Page Faults, and Swap
Page Fault Flow
Process accesses
virtual address X
CPU checks
page table entry
Page IN RAM
→ Access succeeds
OR
Page NOT in RAM
→ PAGE FAULT
Kernel loads page
from swap/disk
→ Resume process

On x86-32, each page is 4096 bytes. If a process accesses an address with no page table entry at all (not in RAM and not in swap), the kernel sends it a SIGSEGV signal — the dreaded segmentation fault.

You can check a process’s page size programmatically with:

long page_size = sysconf(_SC_PAGESIZE);   /* typically 4096 bytes */

Advantages of Virtual Memory
Advantage Explanation
Process Isolation Each process has its own page table pointing to different physical frames — one process cannot read another’s memory
Memory Sharing Multiple processes can map the same physical frames (e.g., shared libraries, shared memory via mmap/shmget)
Memory Protection Page table entries have permission bits (read/write/execute) — text segment is read-only to prevent code corruption
Large Virtual Space A process’s virtual size can exceed physical RAM — swap fills in what doesn’t fit
Better CPU Utilisation Each process uses less RAM, so more processes fit in memory simultaneously, keeping the CPU busier

Code Examples

Example 1: Read the System Page Size
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    long page_sz = sysconf(_SC_PAGESIZE);
    printf("System page size : %ld bytes\n", page_sz);
    printf("                 : %ld KB\n", page_sz / 1024);

    /* Also readable from /proc/meminfo */
    return 0;
}

/* Output (typical x86-64):
   System page size : 4096 bytes
                   : 4 KB  */
Example 2: Trigger a SIGSEGV by Accessing an Invalid Address

When a process dereferences an address with no page table entry, the kernel sends SIGSEGV. This example catches it to explain what happened.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

void segfault_handler(int sig)
{
    printf("\nCaught SIGSEGV (signal %d)!\n", sig);
    printf("We accessed an address with no page table entry.\n");
    printf("Kernel refused access — this is virtual memory protection.\n");
    exit(1);
}

int main(void)
{
    /* Register handler so program doesn't just crash silently */
    signal(SIGSEGV, segfault_handler);

    int *bad_ptr = (int *)0xDEADBEEF;  /* Invalid virtual address */
    printf("About to access invalid address %p ...\n", (void*)bad_ptr);
    *bad_ptr = 42;   /* This triggers a page fault → no entry → SIGSEGV */

    return 0;   /* Never reached */
}

/* Output:
   About to access invalid address 0xdeadbeef ...
   Caught SIGSEGV (signal 11)!
   We accessed an address with no page table entry.
   Kernel refused access — this is virtual memory protection. */
Example 3: Inspect a Process’s Memory Map via /proc

/proc/self/maps shows every virtual memory region the current process has, including permissions and what backs each region.

#include <stdio.h>

int main(void)
{
    FILE *maps = fopen("/proc/self/maps", "r");
    if (!maps) { perror("fopen"); return 1; }

    char line[256];
    printf("%-30s %-6s %s\n", "Address Range", "Perms", "Mapped region");
    printf("%s\n", "---------------------------------------------------------------");

    int count = 0;
    while (fgets(line, sizeof(line), maps) && count++ < 10) {
        printf("%s", line);
    }
    fclose(maps);

    printf("...(truncated — run: cat /proc/self/maps for full output)\n");
    return 0;
}

/* Sample output (x86-64):
   55a3e8400000-55a3e8401000 r--p  /home/user/a.out   (text: read-only)
   55a3e8401000-55a3e8402000 r-xp  /home/user/a.out   (text: execute)
   55a3e8402000-55a3e8403000 r--p  /home/user/a.out   (rodata)
   55a3e8603000-55a3e8604000 rw-p  /home/user/a.out   (data/BSS)
   55a3e9a00000-55a3e9a21000 rw-p  [heap]
   7fff1a200000-7fff1a221000 rw-p  [stack]
   Permissions: r=read, w=write, x=execute, p=private */

Interview Preparation Questions

Q1. What is virtual memory and why does Linux use it?

Virtual memory gives each process a private, isolated address space independent of physical RAM. The kernel maps virtual pages to physical frames via page tables. This provides process isolation, memory protection, shared libraries, and allows a process’s virtual size to exceed physical RAM.

Q2. What is a page fault? When does it become a segfault?

A page fault occurs when a process accesses a virtual address whose page is not currently in RAM. The kernel suspends the process, loads the page from disk (swap), and resumes it. If the address has no valid page table entry at all, the kernel sends SIGSEGV (segmentation fault) instead.

Q3. What is the default page size on x86 Linux and how do you query it?

4096 bytes (4 KB) on x86/x86-64. Query with: long sz = sysconf(_SC_PAGESIZE); or getpagesize(). Some architectures use larger pages (e.g., IA-64 defaults to 16 KB). Huge pages (2 MB or 1 GB) are also available for performance-critical applications.

Q4. How do two processes share the same shared library without duplicating it in RAM?

The kernel makes page table entries in both processes point to the same physical frames containing the library’s text (code). Since the text is read-only, no copying is needed. Each process gets its own copy of the library’s data segment (copy-on-write), but the code is shared.

Q5. What is the “resident set” of a process?

The resident set is the subset of a process’s virtual pages that are currently loaded into physical RAM. The rest reside in swap or have not been accessed yet. You can see it in /proc/PID/status as VmRSS (resident set size).

Q6. What is the PMMU and what role does it play?

The Paged Memory Management Unit (PMMU) is a hardware component of the CPU. Every memory access goes through the PMMU, which translates virtual addresses to physical addresses using the page table. When a page is not in RAM, the PMMU signals a page fault interrupt to the kernel.

Leave a Reply

Your email address will not be published. Required fields are marked *