MemoryMappedFiles

Support for memory-mapped files is another new feature in the .NET Framework 4. Memory-mapped files can be used to edit large files or create shared memory for inter-process communication (IPC). Memory-mapped files allow you to map a file into the address space of a process. Once mapped, an application can simply read or write to memory to access or modify the contents of the file. Since the file is accessed through the operating system’s memory manager, the file is automatically partitioned into a number of pages that are paged in and paged out of memory as needed. This makes working with large files easier, as you don’t have to handle the memory management yourself. It also allows for complete random access to a file without the need for seeking.

Memory-mapped files can be created without a backing file. Such memory-mapped files are backed by the system paging file (only if one exists and the contents needs to be paged out of memory). Memory-mapped files can be shared across multiple processes, which means they’re a great way to create shared memory for interprocess communication. Each mapping can have a name associated with it that other processes can use for opening the same memory-mapped file.

To use memory-mapped files, you must first create a Memory- MappedFile instance using one of the following static factory methods on the System.IO.MemoryMappedFiles.MemoryMappedFile class:


 * 1) CreateFromFile
 * 2) CreateNew
 * 3) CreateOrOpen
 * 4) OpenExisting

After this, you can create one or more views that actually maps the file into the process’s address space. Each view can map all or part of the memory mapped file, and views can overlap.

Using more than one view may be necessary if the file is greater than the size of the process’s logical memory space available for mapping (2GB on a 32-bit machine). You can create a view by calling either the CreateViewStream or CreateViewAccessor methods on the MemoryMappedFile object. CreateViewStream returns an instance of MemoryMappedFileViewStream, which inherits from System.IO.UnmanagedMemoryStream. This can be used like any other Stream in the framework. CreateViewAccessor, on the other hand, returns an instance of MemoryMappedFileViewAccessor, which inherits from the new System.IO.UnmanagedMemoryAccessorclass. UnmanagedMemoryAccessor enables random access, whereas UnmanagedMemoryStream enables sequential access.

Example 1: creates a new MemoryMappedFile instance using the CreateNew method specifying the name of the memory mapped file along with the capacity in bytes. This will create a memory-mapped file backed by the system paging file. Note that internally, the specified capacity is rounded up to the next multiple of the system’s page size (if you’re curious you can get the system page size from Environment.System- PageSize, which is new in .NET 4). Next, a view stream is created using CreateViewStream and “Hello Word!” is written to the stream using an instance of BinaryWriter. Then the second process is started.

using (varmmf = MemoryMappedFile.CreateNew("mymappedfile", 1000)) using (var stream = mmf.CreateViewStream) { var writer = new BinaryWriter(stream); writer.Write("Hello World!"); varstartInfo = new ProcessStartInfo("process2.exe"); startInfo.UseShellExecute = false; Process.Start(startInfo).WaitForExit; }

Example 2: opens the existing memory mapped file using the OpenExisting method, specifying the appropriate name of the memory mapped file. From there, a view stream is created and the string is read using an instance of BinaryReader.

using (varmmf = MemoryMappedFile.OpenExisting("mymappedfile")) using (var stream = mmf.CreateViewStream) { var reader = new BinaryReader(stream); Console.WriteLine(reader.ReadString); }