Skip to content

22/32 · 5 min

Dividing memory by meaning

Paging splits memory into equal blocks that mean nothing. Segmentation splits it by what the parts are for.

Segments

A program has parts with different properties:

code
code     read only, executable, shared between processes
data     read write, fixed size
heap     read write, grows upward
stack    read write, grows downward

A segmented address is a segment number plus an offset within it, and each segment has its own base, length and permissions.

What that buys

Protection that matches meaning. Code is marked non writable, so a bug cannot overwrite instructions. The stack is marked non executable, which is what stops a classic buffer overflow from running injected code. That protection is per segment because the segments mean something.

Sharing. Twenty copies of the same program share one physical copy of the code segment.

Bounds checking. An offset past the segment length is caught by hardware, which is where a segmentation fault comes from.

What it costs

Segments have different sizes, so external fragmentation returns exactly as in contiguous allocation. And a segment must be contiguous in physical memory, so a large growing heap can fail even with plenty free.

Both together

Modern systems segment for meaning and page for placement. Each segment is paged, so it need not be contiguous, and the permissions still apply per segment.

code
logical address -> segment number + offset
                -> segment table gives a page table
                -> page number + offset -> frame

x86 supported full segmentation and 64 bit mode largely abandoned it, keeping only enough to separate user and kernel. The naming survives everywhere else: the text, data, bss, heap and stack regions of a process are segments, and SIGSEGV is named after them.

PagingSegmentation
Unitfixed sizevariable, logical
Visible to the programmernoyes
Fragmentationinternalexternal
Protection granularityper pageper logical region