Understanding "Flat memory model" and "Segmented memory model"

The memory model in use is determined by two things:

  1. The CPU in use, and what modes it supports
  2. The Operating System and what it uses

From a programmer's point of view, unless you're working on kernel code, you get what the OS gives you. Which in most modern operating systems is a paged memory model.

For code that will execute on a modern operating system in userspace, the memory model as far as the process is concerned is flat. This is because the OS provides a virtual memory space to the process that hides all of the paging, swapping, and other things that can happen to memory. This layer of abstraction is quite, quite useful since it doesn't force programmers to play nice with memory for the good of the whole system.

Historically, this wasn't always the case.

Windows 3.1x, MacOS up to v9, and Novell NetWare all lacked some of the memory protections we take for granted in Linux/Windows/OSX. NetWare in specific had one big memory space it provided to all running code, so one bug that attempted to access memory it wasn't actually assigned could actually get that memory and more often than not crash the whole system. Programmers programming for NetWare had to be very careful about memory management for this reason, and to an extent that Linux/windows/OSX programmers don't need to bother with.

And yet even NetWare used a Paged Model of memory, it just didn't provide each process with a virtual memory-space, it gave it the actual memory space.

The memory model in use is not flexible for all programming but the closest to the hardware. Kernel programming and embedded device programming are the areas where such things are very important.


"Memory model" is both a low-level and a (relatively) high-level concept.

Back in the olden days there was a bit of a "war" raging between processors with a segmented memory model and those with a "paged" or "mapped" memory model. The Burroughs B5000 series machines and the Plessey 250 used a segmented memory model with "capabilities" (or "descriptors"). That is, physical storage was not managed as conceptual fixed-size pages but rather variable-length segments, with each segment corresponding to some logical entity (eg, a procedure or an object). To address between segments "capability registers" were used that could only be loaded in a protected fashion and which contained the physical address of a segment, the length of the segment, and the authorizations (eg, read/write/execute) that the executing program was given to reference the segment.

These systems were happily running when "paged" systems were still struggling to get off the ground.

The original PC was based on the 8086 processor which was designed to support a poor-man's segmented architecture. There were, IIRC, four segment registers that could be selected to be added to a 16-bit general register value to produce a 20-bit address. The theory was that these registers would be managed in software somewhat similar to how the Burroughs and Plessey systems managed them with a bit more hardware support. But before good software could be produced to make use of this feature DOS was kludged onto the 8086, and so the feature was never really used effectively.

As to which is better, well, it doesn't matter anymore, since the segmented model doesn't exist in any "real" (non-experimental) environment. But back in the day the segmented model generally performed better and allowed the OS to be more robust. The major negative factor was that it imposed restrictions on compilers and, to an extent, programmers that were not consistent with the "Wild West" attitudes of many programmers then and now.

The "paged" model

A "paged" model assumes the address space is divided into "pages" of a certain size (though in some cases several different page sizes are supported). Generally the page size is somewhere between 256 bytes and 64k bytes (always a power of 2). It is also assumed that the hardware contains some sort of address translation support so that "logical" addresses (addresses in the program's "address space") can be mapped to "physical" addresses (addresses in RAM).

A paged model may be implemented for two main reasons:

  1. To allow multiple different threads/processes to have separate address spaces, each starting from "zero" (or some other standard address), and without requiring to OS to pre-allocate the entire possible address space for a thread/process as one contiguous chunk.
  2. To enable "virtual memory" by allowing individual pages in the logical address space to be "paged out" to disk, to be later reloaded if/when the program attempts to reference them.

There are also minor features of the page translation hardware that may be used, such as setting read/write/execute permissions, allowing some pages to be "shared" between processes/threads, etc.

The "flat" model

Ignoring the Harvard model, which was arguably the very first computer memory model, the flat von Neumann storage model was first model to achieve common use. This is basically that -- a "flat" address space of undistinguished words (not bytes until very late in the game) that began at address zero and continued upward to the "top" of available memory. Some portion of memory at the "bottom" or "top" of memory would be reserved for some sort of "loader", with the rest available to the single executing program. One program at a time ran, with the program able to use all but that small reserved RAM area.

Slowly things changed, to where the small reserved area became larger and held an operating system of sorts, but still only one program at a time. As time progressed still further, various tricks were invented to allow, eg, certain specialized programs to run in a "corner" of memory, permitting spooling programs, etc, to co-exist with the user's programs.

But the push for "multiprogramming" was exerting pressure. Some systems added crude address mapping hardware to enable multiple programs to each have their own address space. Other systems required that programs be "self relocating" so that they could run anywhere in memory vs being "linked" to a specific address.

Early Unix (among others) handled the multiprogramming job by "swapping" programs in and out: A program (loaded at address zero) would run until it "blocked" to do I/O, then it would be "swapped" (in its entirety, including all code and data) to disk and a different program "swapped" in.

But for the most part these techniques slowly evolved (or perhaps devolved) to various forms of page-mapping storage models.


I'm a programmer, but not an embedded programmer who actually has to deal with memory models at this level, so take what I say with a grain of salt.

My understanding is that memory models are determined by the processor architecture. They'd be most relevant to a programmer working with assembly, low-level C, or anything that is close to the hardware. With many higher level languages, like Java or C#, there are abstractions that hide details like these from you, so you don't usually have to think about hardware memory models.

There are weird times when it does come up. It's my understanding that 32-bit x86 processors (for the last decade, at least) can access more than 4GB of memory using segments (PAE Mode), any many 32-bit OSes support it, but then the maximum amount of memory a single process can use is limited to 4GB, because most programs expect a flat memory model (and I doubt many modern OSes would allow them to expect anything else).

To clarify the quotes:

  1. Early x86 processors had a memory model that was a lot like a set of numbered drawers with smaller numbered compartments in them. To access a bit of memory, you'd have to specify the drawer number along with the compartment number. All the drawers were the same, some programmers would just decide to use one drawer for code, another for data, etc., but those decisions weren't dictated by the processor architecture. A flat memory model is like having exactly one drawer, so you just use the compartment number.

  2. Without extra features (like ones that prevent one program from using another program's memory), a flat memory model isn't suited for modern operating systems, but all modern desktop/server processors have had these features for decades.

  3. All x86 processors have modes that access memory just like an 8086, 80286, etc for backwards compatibility, but they're obsolete. Pretty much no one uses them anymore, and they always switch to more modern modes.

Hope this helps.


Memory segmentation is the division of computer's primary memory into segments or sections. Segments or sections are also used in object files of compiled programs when they are linked together into a program image, or when the image is loaded into memory. In a computer system using segmentation, a reference to a memory location includes a value that identifies a segment and an offset within that segment. Different segments may be created for different program modules, or for different classes of memory usage such as code and data segments. Certain segments may even be shared between programs