Windows Memory Management (from Inside Windows NT)
System address space layout in NT
2GB of user address space - mapped as needed
2GB of system address space - mapped as needed, but generally invisible or read/only
User address space layout
64K of inaccessible space to catch null pointers, and then some
2GB - 192K or more = user process address space, possibly sharable
At the top:
4KB or more = Thread environment blocks (TEBs) for threads
4KB = Process environment block (PEB)
4KB = shared user data page - read/only system time, clock tick count, etc.
60KB = no-access region above the shared user data
64KB = more no-access region to prevent threads from using buffers that might straddle the boundary between user and system address spaces
The Windows 95-98 Problem
System address space (similar memory map) was R/W to user processes.
Process address space
Chunks of the virtual address space are free, reserved, or committed
Free = not used at all
If an instruction touches that address, you get a memory error
May be allocated to the process (reserved or committed)
Reserve = A process/thread requests more address space for RAM
Allocates address space
If another thread asks for more address space, it gets a different piece
RAM not yet allocated - accesses will cause memory errors
Commit = Allocate some actual RAM to the address space
Allocates actual RAM to the process
Actually, it sets aside space in the paging file on the hard drive
RAM gets "paged in" when the process actually refers to it
The RAM may be private or may be visible to other processes through a section object
Why Reserve/Commit
Page file space is a precious commodity - it's expensive to manage a gigantic page file, and the system slows down as paging increases
Programs often need to set aside a big chunk of address space, but they don't need it all at once
Example: stack space
Process reserves a large chunk (1MB or more) for the stack
Process commits only 2 pages: the current stack page and a "guard" page for when the stack fills up the current page
Example: large data buffer or array
Process reserves space for the entire array
Process commits RAM as parts of the buffer get used, and decommits as the space becomes unnecessary - this makes some programming tasks easy, since the programmer has to do less memory management
More on Guard Pages
A guard page is a page that will probably be used, but we don't want to commit to using until it's really needed
A guard page can become a working page when a memory fault indicates that it's needed. Example: a stack flowing onto a guard page
Shared memory
Section objects and file mapping objects (more or less the same thing)
Can point to a file on the hard drive (i.e. a program's executable image, or other read-only data)
Can point to a chunk of the paging file - for read/write RAM shared by two or more processes
Copy-on-write
Optimization intended to conserve physical RAM
Read/write section objects are implemented as a set of copy-on-write pages
If processes don't change a particular page, they continue to share the same image of that page in a single page frame
If one of the processes tries to write to a shared page:
it causes a memory fault that interrupts the process
Memory manager allocates a new page frame for that page
MMgr copies the page to the new page frame
MMgr gives the faulted process private r/w access to the new frame
MMgr restarts the faulted process
Why it's used
The classic Unix fork() primitive shares a single address space between two processes: the parent and the (forked) child
Example of lazy evaluation - process of not committing to an expensive activity until you're absolutely certain it's needed
Kernel RAM
Non-Paged Pool
For activities that can't be paged, like I/O operations
I/O transfers often use DMA, which bypasses virtual memory mapping and can't rely on paging
Anything that's accessed by interrupt routines must be in non-paged RAM since interrupt routines can't wait for a page fault
Paged Pool
Activities that can be paged: message buffers passed between processes (maybe)
What's in System Address Space?
P. 246-247 of Inside NT
Memory manager software
Executive services (APIs) to manipulate the address space and RAM (commit, etc)
Fault handler for page faults and other access faults related to RAM and VM
Kernel mode system threads handling RAM (6 of them)
Balance set manager - assess working set sizes (downward preferably), aging pages, writing modified pages to the paging file. It does the "policy work" and passes the actual work off to other system threads
Process/Stack swapper - ensures that process and kernel stacks are swapped in or out as appropriate
Modified page writer - support for balance set manager. Only runs when there are "too many" modified pages sitting around
Mapped page writer - writes mapped (shared) pages to the HD. Must be separate from the other, because it can cause page faults and require a free page. This would cause a deadlock if both tasks were in one thread.
System cache and page file thread - makes page file larger as needed and manages the system cache.
Zero page thread - fills all free pages with zeroes - they must be zeroized before being given to a new process as a free page.
Windows Virtual Addresses
Three Level virtual addresses
10 bits = page directory index
10 bits = page table index
12 bits = offset into the page
Page tables may be "system" tables or "process" tables, depending on where the virtual address reference is pointing
Translation lookaside buffer (cache)
It takes 2 extra memory references to use a 2-level page table: bad for performance
TLB is a special "associative" RAM that keeps the most recent virtual to physical memory mappings
If the virtual memory reference is in the TLB, it saves 2 memory references
Page replacement policy
Uses a version of the clock algorithm - a compromise between FIFO and LRU
Page replacement usually happens after "trimming" the working set of a process - reducing the number of pages the process will keep in RAM