The VikiD Truth

Knowledge base / Computing

computingFreedom | Build | Picolisp | Picolisp Machine | pil sources | Linux | BASH | C Programmming | Operating Systems | Javascipt | Emacs | vim | Pharo Smalltalk | Computer Security | Python | SimpleLinuxConfig

Linux Memory and Process

The truth behind every running program on Linux: each process believes it has the whole machine’s memory to itself. It doesn’t. The kernel and the CPU are running a very convincing illusion called virtual memory, and once you see how it’s staged, processes stop being mysterious.

What it is, in plain words

A process is a running program: some code, some memory, some open files, and a bit of kernel bookkeeping (a PID, an owner, a state, a parent). On Linux every process gets its own virtual address space – on x86-64 a range of 128 TiB for user space. The addresses your program uses are not physical RAM addresses; the CPU’s memory management unit translates them, page by page (usually 4 KiB per page), using page tables the kernel keeps for each process.

Inside that space a process is laid out in regions:

flowchart TB
  A["High addresses<br/>kernel (invisible to the process)"]
  B["Stack – grows down<br/>local variables, return addresses"]
  C["Memory-mapped area<br/>shared libraries, mmap'd files, big mallocs, thread stacks"]
  D["Heap – grows up<br/>malloc / new"]
  E[".bss – zeroed globals"]
  F[".data – initialised globals"]
  G[".text – machine code (read + execute)"]
  A --- B --- C --- D --- E --- F --- G

Address Space Layout Randomization (ASLR) shuffles the start of each region every run, which is why addresses differ each time.

Why it matters

Almost every hard bug and every interesting security issue lives here: stack overflows, use-after-free, memory leaks, segmentation faults, “the OOM killer took my database”. Performance too – cache misses and page faults are where time goes. And understanding the layout tells you why one process can’t scribble over another’s memory: they literally can’t name each other’s addresses.

An everyday analogy: hotel room numbers

Every guest in a hotel chain is told “you’re in room 101”. In every hotel, a different guest is in “room 101” – it’s a different building. The front desk (the MMU, guided by the kernel) knows which real room each guest’s “101” maps to. Guests can’t wander into another building’s 101. And some rooms – the shared lobby, the restaurant – appear in everyone’s map: those are shared libraries.

A hands-on example: see it for yourself

/* layout.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int initialised = 42;   /* .data */
int zeroed;             /* .bss  */

int main(void) {
    int local = 1;                       /* stack */
    int *heap = malloc(sizeof *heap);    /* heap  */
    printf("pid    %d\n", getpid());
    printf("text   %p\n", (void *)main);
    printf("data   %p\n", (void *)&initialised);
    printf("bss    %p\n", (void *)&zeroed);
    printf("heap   %p\n", (void *)heap);
    printf("stack  %p\n", (void *)&local);
    getchar();                           /* pause so we can look */
    return 0;
}
gcc -g layout.c -o layout && ./layout

In a second terminal, using the PID it printed:

cat /proc/<pid>/maps        # every region, with permissions
pmap -x <pid>               # same, with sizes and RSS
grep -E 'Vm|Rss' /proc/<pid>/status

You’ll see the addresses printed by the program land neatly inside the regions the kernel lists. Run it twice: thanks to ASLR, the numbers change.

How processes are born and die

Linux creates processes with fork (copy myself) and exec (replace my program with another). The copy is cheap because of copy-on-write: parent and child share pages until one of them writes, and only then is a page actually copied.

ps -eo pid,ppid,stat,rss,vsz,comm --forest | head -20

STAT letters tell you the state: R running, S sleeping, D uninterruptible (usually waiting on disk), Z zombie (finished, parent hasn’t collected the exit status), T stopped. On Vikix, PID 1 is runit; on most other distros it’s systemd.

When memory runs out

Linux overcommits: malloc usually succeeds even if RAM is short, because many programs never touch all they ask for. Pages are only really allocated when touched (a page fault brings them in). If real memory then runs out and swap (or zram) can’t help, the OOM killer picks a process to kill. Check dmesg or the journal for “Out of memory: Killed process”. Modern desktops increasingly use userspace helpers like earlyoom or systemd-oomd to act before the system freezes.

Common misconceptions

Connections

Last edited · 2 revisions

Tags: #Computing