How the Windows NT Virtual Memory System Works

You probably know that Windows NT is a 32-bit operating system that runs both 16-bit and 32-bit applications. Even the system calls of 16-bit applications are translated to 32 bits.

What does this mean? A program can see 32 bits worth of address space. This translates to 4 gigabytes (4 billion bytes) of virtual memory. The upper half of this is devoted to system code and data and is only visible to the process when it is in privileged mode. The lower half—2 billion bytes—is available to the user program when it is in user mode, and to those user-mode system services called by the program.

Furthermore, the RAM on your Windows NT computer is divided into two categories: nonpaged and paged. Nonpaged code or data must stay in memory and cannot be written to or retrieved from peripherals. Peripherals include disks, the LAN, a CD-ROM, and other devices. Paged memory is RAM which the system can use and later reuse to hold various pages of memory from peripherals. Paged memory is divided into page frames, that hold various pages from time to time much as a picture frame can hold various pictures.

Page size varies with the computer's processor type. Page size is 4096 bytes (4K) for 386, 486, and Pentium processors, the same for MIPS® processors, and 8192 (8K) for DEC® Alpha processors. Varying page size is the reason many Performance Monitor counters are in bytes: 100 pages of data is not the same amount of data on all computers.

When a page of code or data is required from a peripheral, the Windows NT memory manager finds a free page frame in which to place the required page. The system transfers the required page, and processing can continue. If no page frame is free, the memory manager must select one to reuse. The memory manager tries to find a page frame whose contents have not been referenced for a while. When the memory manager finds a suitable page frame, it discards the page in it if that page has not been modified since it was placed into RAM. Otherwise, the changed page must be written back to its original location on the peripheral before the new page can replace it. The memory manager has lots of tricks to minimize and anticipate the flow of pages and thus reduce the possibility that paging traffic will beat the peripherals into abject misery. We'll discuss a few of these as we go along.

Normally, programs execute by fetching one instruction after another from a code page (a page that contains program instructions) until they call or return to a routine in some other code page, or make a jump to code in another page. Or, they can simply run off the end of the current page and need the next one. Such a transfer of instruction control to a new page causes a page fault if the needed page is not currently in the working set of the process. The working set of the process is the set of pages currently visible to the process in RAM.

A page fault can be resolved quickly if the memory manager finds the page elsewhere in RAM. It might be in the working set of some other process or processes, or it might have been removed from this process's working set by the memory manager in an overzealous attempt to keep the process trim and fit. The memory manager places such pages on a list of page frames called the standby list, and they can be reinserted into a process's working set lickety-split. But if the page is not in RAM somewhere, the memory manager must find a free page frame, or make one free as described above, and then fetch the required page from the peripheral. One characteristic of code pages is it isn't normal for code to be modified while in RAM, so code pages can be discarded without being written back to disk.

Data pages, which contain data used by a program, are accessed in a somewhat more random fashion than code pages. Each instruction in a program can reference data allocated anywhere in the address space of a process. The principle, however, is much the same. If an attempt is made to access a data page not in the working set of the process, a page fault occurs. From that point on, the process is just as described for code pages. The only difference between data pages and code pages is that data pages are frequently changed by the processes that access them, and so the memory manager must take care to write them on the peripheral before replacing them with another page. A general page fault handling diagram appears in Figure 5.1.

Figure 5.1 Handling page faults on Windows NT