As for memory mapped files methods, they provide us the way to treat files on the disk as they were loaded in dynamic memory. Using memory mapped file we can map part or full file to the memory address in our process space.
Now read/write are as simple as doing it with dynamic memory. All memory related operation internally are handled by the Virtual memory manager.
It uses paging and caching to optimize the io operation.
This leads to the less actual hard disk read/write. Additionally we do not need to load whole file. Memory mapped files can be used to share a common memory between two processes. Common memory object is given a name and name is used by different processes to access it. Win 32 API exposes various method to achieve MMF like ,CreateFileMapping(),OpenFileMapping(),MapViewOfFile() etc.
For managed code developers we got it under System.IO .
using System.IO;
using System.IO.MemoryMappedFiles;
//Process 1
private static void MMFileWrite()
{
MemoryMappedFileSecurity CustomSecurity =
new MemoryMappedFileSecurity();
MemoryMappedFile memFileObject =
MemoryMappedFile.CreateFromFile(
new FileStream(@"C:\MyMemMapFile.map",
FileMode.Create,FileAccess.ReadWrite,
FileShare.ReadWrite),
"MyMapFile", //Name
1024 * 1024, //Size
MemoryMappedFileAccess.ReadWrite,
CustomSecurity,
HandleInheritability.Inheritable,//Child processes
false);// Dispose filestream
using(MemoryMappedViewAccessor view
= memFileObject.CreateViewAccessor())
{
MyMemContent content =
content = new MyMemContent();
content.Id = 1;
content.High = 45;
content.Low = 39;
content.Bid = 43;
content.Close = 42;
view.Write(1,ref content);
}
}
Memory mapped file should have shared attribute so that , processes accessing it can read / write.
//Process 2
private static void MMFileRead()
{
MemoryMappedFile memFileObject
= MemoryMappedFile.OpenExisting(
@"MyMapFile",
MemoryMappedFileRights.FullControl,
HandleInheritability.Inheritable);
using (MemoryMappedViewAccessor view
= memFileObject.CreateViewAccessor())
{
MyMemContent content =
content = new MyMemContent();
view.Read(1, out content);
}
}
There is another thing , if we dispose the MemoryMappedFile object , then the file is no more accessible for read/write operation. Content to be written to the memory file should be of value type and if we are wrtting the custom structure to file then it should not contain any reference type.
Hi, i create console aplication using your sample... And i have problem, two process not open file. Please can you see?
ReplyDeleteusing System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
namespace MemoryFileTest
{
class Program
{
static void Main(string[] args)
{
var path = @"c:\work\mmf.dat";
var map = "testmap123";
var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
if (fs.Length == 0)
{
fs.SetLength(1024);
}
try
{
var sec = new MemoryMappedFileSecurity();
var mem = MemoryMappedFile.CreateFromFile(fs, map, fs.Length, MemoryMappedFileAccess.ReadWrite, sec, HandleInheritability.Inheritable, false);
WriteRole(mem);
}
catch (Exception exp)
{
fs.Close();
var mem = MemoryMappedFile.OpenExisting(map, MemoryMappedFileRights.FullControl, HandleInheritability.Inheritable);
ReadRole(mem);
}
}
static void WriteRole(MemoryMappedFile mem)
{
Console.WriteLine("Begin write role.");
var ptr = mem.CreateViewAccessor(0, 1024, MemoryMappedFileAccess.ReadWrite);
while (true)
{
int mode;
ptr.Read(0, out mode);
if (mode < 2)
{
Console.WriteLine("Write new time to my friend.");
var str = DateTime.Now.ToString();
var pos = 4l;
ptr.Write(pos, str.Length);
pos += 4;
for (int i = 0; i < str.Length; ++i)
{
ptr.Write(pos, str[i]);
pos += 2;
}
ptr.Write(0, 2);
}
Thread.CurrentThread.Join(500);
}
}
static void ReadRole(MemoryMappedFile mem)
{
Console.WriteLine("Begin read role.");
var ptr = mem.CreateViewAccessor(0, 1024, MemoryMappedFileAccess.ReadWrite);
while (true)
{
int mode;
ptr.Read(0, out mode);
if (mode == 2)
{
var pos = 4l;
var len = ptr.ReadInt32(pos);
var arr = new char[len];
pos += 4;
for (int i = 0; i < len; ++i)
{
arr[i] = ptr.ReadChar(pos);
pos += 2;
}
var str = new string(arr);
Console.WriteLine(str);
ptr.Write(0, 1);
}
Thread.CurrentThread.Join(500);
}
}
}
}