MS-DOS 6.22 Upper Memory Block Fragmentation
This article explains how MS-DOS 6.22 manages Upper Memory Block (UMB) fragmentation within the Upper Memory Area (UMA). Because the 16-bit real-mode architecture of MS-DOS prevents runtime memory compaction or dynamic defragmentation, the operating system relies on static allocation strategies, Memory Control Block (MCB) chains, and load-order optimization through utilities like MemMaker to mitigate fragmented memory regions.
The Real-Mode Constraint on Defragmentation
MS-DOS 6.22 runs primarily in real mode, meaning running programs and drivers rely on hardcoded, segmented memory addresses (segment:offset). Once a Terminate-and-Stay-Resident (TSR) program or device driver loads into memory, it cannot be dynamically relocated to another address space. Consequently, MS-DOS cannot perform active or run-time memory defragmentation on UMBs. Once a memory hole forms between two resident programs in upper memory, that space remains fragmented until the system is rebooted.
EMM386 and Memory Control Blocks
UMB management begins with HIMEM.SYS and
EMM386.EXE. When DOS=UMB is specified in
CONFIG.SYS, the DOS kernel links the Upper Memory Area
(addresses between 640 KB and 1024 KB) into its global memory pool.
EMM386 detects unused address space between video RAM, system ROMs,
and adapter cards, mapping extended memory pages into these gaps. DOS
organizes each identified continuous pocket of memory using standard
Memory Control Blocks (MCBs). If the UMA is physically split by hardware
(for example, video RAM at A000h–C7FFh and network adapter
ROM at D000h–D7FFh), DOS creates distinct, non-contiguous
UMB regions, each governed by its own chain of MCBs.
Allocation Strategies: First Fit, Best Fit, and Last Fit
To prevent premature fragmentation when software requests memory, MS-DOS 6.22 uses configurable memory allocation strategies accessible through Interrupt 21h, Function 58h:
- First Fit: DOS searches from the lowest available memory address and allocates the first block large enough to satisfy the request. While fast, this method often leaves small, unusable slivers of memory dispersed across the UMA.
- Best Fit: DOS scans all available blocks in the UMB pool and allocates the one closest in size to the requested amount. This leaves larger contiguous regions intact for subsequent, larger drivers, directly minimizing fragmentation.
- Last Fit: DOS searches from the highest memory address downward, packing drivers toward the top of the UMB space.
By default, DOS uses First Fit, but specialized configuration utilities adjust these flags before placing drivers.
Regional Segmentation with the /L Switch
MS-DOS 6.22 introduced fine-grained placement controls for
DEVICEHIGH (in CONFIG.SYS) and
LOADHIGH (in AUTOEXEC.BAT) via the
/L parameter. The /L switch enables an
administrator to specify which distinct UMB region a program must occupy
(e.g., /L:1 or /L:2).
Furthermore, many drivers require more memory during initialization
than they do while idling as a resident process. The /L
switch accommodates this by allowing an initialization size parameter
(e.g., /L:1,12048). DOS ensures that the specified UMB
region has enough temporary space to accommodate the initialization
footprint without spilling over into or fragmenting adjacent
regions.
Automated Optimization via MemMaker
Because MS-DOS 6.22 cannot defragment upper memory dynamically, it
addresses fragmentation through preventative pre-allocation via the
MEMMAKER utility.
MemMaker resolves fragmentation statically by performing test
reboots. During these boots, it measures both the transient
initialization size and the final resident size of every driver and TSR.
It then calculates an optimal loading sequence using a bin-packing
algorithm. By ordering the load commands so that drivers requiring large
initialization footprints load first, and by locking programs into
designated UMB regions via the /L switch, MemMaker packs
drivers tightly against one another, effectively eliminating dead space
and preventing unusable memory fragments before the operating system
finishes booting.