File Mapping and Memory Sharing
A powerful feature of the NT Memory Manager is that it lets programs map
files into their virtual address space. This mapping is accomplished in two
steps. In the first step, the program creates an object, called a Section
Object, to describe a file that the Memory Manager can map. The Section Object
holds information about the name of a file, its size, and what portions of it
are mapped. The Win32 function CreateFileMapping results in a Section Object's
creation.
In the second step, the program maps all or part of the file into the
process address space. The process invokes the Win32 function MapViewOfFile to
do this mapping, specifying the start offset in the file to begin mapping and
the number of bytes to map. The process specifies the protection (e.g.,
read-only, read/write) on the view at this time. After the view is mapped, the
process can read to and write from the file simply by reading and writing data
to the view's addresses in the process address map. The Memory Manager
transparently works with the file systems to ensure that all processes accessing
the file see any updates the original process makes and that the updates are
eventually flushed to disk.
The file-mapping capability makes file I/O extremely straightforward, and
NT uses it extensively. When an application launches, the Process Manager maps a
view of the application's image to the address space of the application's
process. The Process Manager transfers control to the entry point of the image
in the address space, and as the application executes, any pages referenced for
the first time generate page faults. The page faults result in the Memory
Manager reading the applications pages from the file on disk.
NT uses a variation of file mapping to share memory. In this variation,
MapViewOfFile takes a parameter that specifies memory mapping, rather than file
mapping. The Memory Manager backs views of the section with the paging file when
memory mapping is specified. The data in the view is no different from regular
virtual memory that a process reserves and commits. However, NT can give
sections of the data names in the Object Manager namespace so that two
or more processes can open the same section, map views to their own address
spaces, and then communicate with one another through this shared memory.
Copy-on-Write
The Memory Manager implements an important optimization of memory sharing
called copy-on-write. There are several common scenarios in which a process
might want to use the same data as another process but keep any modifications it
makes private to itself. For example, if two or more processes start the same
application and one process modifies the data in the image, other processes
should not see that modification. The obvious way to accomplish this kind of
private modification is to load multiple copies of the application into memory;
however, this strategy wastes space. Instead, the Memory Manager marks the
physical pages containing the image read-only and notes in an internal data
structure (which I'll describe next month) that the page is a copy-on-write
page. When a process tries to modify the copy-on-write page, that action will
generate a page fault (because the page is read-only). The Memory Manager will
see that the process referenced a copy-on-write page and will copy the contents
of the copy-on-write page to another page that is private to the process that
made the reference. Then, when the faulting instruction restarts, the process
can modify its private copy of the page. Figure 5 demonstrates this procedure.
In the figure, Process 1 and Process 2 share three copy-on-write pages. If
Process 1 writes to one of the pages, it will get its own private copy of the
page, and Process 2 will retain the original of the page.
NT uses the copy-on-write functionality mostly for executable images. When
programs start, the Process Manager maps copy-on-write images. The POSIX
subsystem also uses copy-on-write for handling the POSIX fork operation. When a
POSIX process forks, the Process Manager creates a child process that will
inherit the address space of the parent process. Instead of making a copy of all
the parent's memory, the Memory Manager just marks the address-space pages of
both the parent and child processes as copy-on-write. When either process makes
a modification to its memory, it receives a private copy of the page it wants to
modify, and the original of the page will then be private to the other process.
Stay Tuned
Next month, I'll dig deeper into the Memory Manager to describe the internal
data structures it uses to keep track of pages. I'll present the details of how
the Memory Manager implements shared memory, and I'll give you an overview of
the way working sets--the amount of physical memory assigned to each
process--are tuned as the system runs.
End of Article
Prev. page
1
2
3
[4]
next page -->