Memory management is the way in which an operating system allows applications to access memory, either for private use by a single application or to be shared between applications. In either case, it is the responsibility of the operating system's memory management component to supervise the correct use of memory and to ensure that no application gains access to memory outside its own address space.
Previous versions of OS/2 were based upon the Intel 80286 processor architecture. In this architecture, there is a limitation on the amount of memory that can be addressed as a single unit. This is due to the fact that memory is managed in segments of up to 64KB in size. Previous versions of OS/2 maintained a series of descriptor tables for memory segments, and 16 bits were allocated in each table entry for the length of the segment. Thus, each descriptor table entry gave access to a segment of up to 2^16 = 64KB in size.
The particular implementation of the segmented memory model within the 80286 processor allowed a minimum segment size of 1 byte. Hence an application could request the allocation of a memory segment from 1 byte to 64KB in size, in a single operation. These segments formed the basis of memory allocation within the system, and of the virtual memory implementation by which memory overcommitment was supported.
If the need arose for more than 64KB to be used for a single memory object or data structure, the programmer and the operating system had to take this limitation into consideration, and implement appropriate algorithms to use multiple memory segments for a single logical structure.
OS/2 Version 2.0, however, is based upon the Intel 80386 processor architecture. This processor has a 32-bit addressing scheme in place of the 24-bit overlapped scheme used in the 80286, thereby giving access to 2^32 = 4GB of memory in a single logical unit.
However, if a unit of this size were to be allocated and manipulated in the same segment-oriented manner as implemented in the 80286, severe problems would arise. For instance, the segment could potentially be larger than the available memory in the system. An alternative mechanism for memory manipulation is therefore required with the 80386.
In the 80386 architecture, memory is split into fixed size units of 4KB. All memory allocation, addressing, swapping and protection is based on pages. As with previous versions of OS/2 the total memory, allocated to all processes running in the system, may exceed the physical memory available. Memory objects or parts of memory objects, which are not required by the currently executing process, may be temporarily migrated out to secondary storage (disk). When used with a paged memory management scheme, this procedure is known as paging. An application may request a large amount of memory, in which case multiple pages are allocated. However, since virtual memory is managed on a page-by-page basis, such units of storage may now exist partly in real memory and partly in a file on disk, thereby significantly easing the constraints on memory overcommitment.
OS/2 Version 1.3 moved complete segments between main memory and the swap file. The fact that segments were variable in length complicated the management of both main memory and space in the swap file. There was also the requirement to compress memory regularly to reclaim the gaps, which formed when memory was freed. Under OS/2 V2.0, in most cases there is no requirement to find contiguous pages in memory to satisfy an allocation request. Consequently there is no need to move pages around in memory. The exception to this is the need for buffers used in DMA I/O transfer, which must be in contiguous locations in memory.
The remainder of this chapter will explore the memory management capabilities of the 80386, as implemented by OS/2 Version 2.0, in more detail.