Programs generally divide up their memory usage by function. Some memory holds instructions, some static data, some dynamically-llocated data, some execution frames. All of these memory types have different protection, growth, and sharing requirements. In the monolithic memory allocation of classic VM systems, this model isn't well supported.

Segmentation addresses this by providing multiple sharable, protectable, growable address spaces that processes can access.


Of course, the segment name space must be carefully managed, and ths OS must provide a method of doing this. The file system can come to the rescue here - a process can ask for a file to be mapped into a segment and have the OS return the segment register to use. This is known as memory mapping files. It's slightly different from memory mapping devices, because one file system abstraction (a segment) is providing an interface to another (a file). Memory mapped files may be reflected into the file system or not and may be shared or not at the process's discretion.
The biggest problem with segmentation is the same as with varaible sized real memory allocation: managing variable sized partitions can be very inefficient, especially when the segments are large compared to physical memory. Checkerboarding, or external fragmentation, can easily result in expensive compaction when a large segment is loaded, and swapping large segments (even when compaction is not required) can be costly.
One solution to the problems with pure segmentation is the same one applied to variable partitions: paging. In this case each segment is paged just like address spaces are in pure paging systems. To resolve a memory reference, the MMU:
Of course multilevel page tables (and even multi-level segment tables) can make the memory usage more efficient.
The Multics system implemented such a paged segmentation system. (Multics' strategy was "all the world's a segment."1 Files, libraries, prohrams were all memory segments.)