Minnesmappade filer
En minnesmappad fil innehåller innehållet i en fil i det virtuella minnet. Den här mappningen mellan en fil och ett minnesutrymme gör det möjligt för ett program, inklusive flera processer, att ändra filen genom att läsa och skriva direkt till minnet. Du kan använda hanterad kod för att komma åt minnesmappade filer på samma sätt som inbyggda Windows-funktioner får åtkomst till minnesmappade filer, enligt beskrivningen i Hantera minnesmappade filer.
Det finns två typer av minnesmappade filer:
Bevarade minnesmappade filer
Bevarade filer är minnesmappade filer som är associerade med en källfil på en disk. När den senaste processen har slutförts med filen sparas data i källfilen på disken. Dessa minnesmappade filer är lämpliga för att arbeta med extremt stora källfiler.
Icke-bevarade minnesmappade filer
Icke-bevarade filer är minnesmappade filer som inte är associerade med en fil på en disk. När den senaste processen har slutförts med filen går data förlorade och filen återvinns av skräpinsamling. Dessa filer är lämpliga för att skapa delat minne för kommunikation mellan processer (IPC).
Processer, vyer och hantering av minne
Minnesmappade filer kan delas mellan flera processer. Processer kan mappas till samma minnesmappade fil med hjälp av ett gemensamt namn som tilldelas av processen som skapade filen.
Om du vill arbeta med en minnesmappad fil måste du skapa en vy över hela den minnesmappade filen eller en del av den. Du kan också skapa flera vyer till samma del av den minnesmappade filen och därmed skapa samtidigt minne. För att två vyer ska förbli samtidiga måste de skapas från samma minnesmappade fil.
Flera vyer kan också vara nödvändiga om filen är större än storleken på programmets logiska minnesutrymme som är tillgängligt för minnesmappning (2 GB på en 32-bitars dator).
Det finns två typer av vyer: dataströmåtkomstvy och slumpmässig åtkomstvy. Använd dataströmåtkomstvyer för sekventiell åtkomst till en fil. Detta rekommenderas för icke-bevarade filer och IPC. Slumpmässiga åtkomstvyer rekommenderas för att arbeta med bevarade filer.
Minnesmappade filer nås via operativsystemets minneshanterare, så filen partitioneras automatiskt till ett antal sidor och nås efter behov. Du behöver inte hantera minneshanteringen själv.
Följande bild visar hur flera processer kan ha flera och överlappande vyer till samma minnesmappade fil samtidigt.
Följande bild visar flera och överlappande vyer till en minnesmappad fil:
Programmering med minnesmappade filer
Följande tabell innehåller en guide för att använda minnesmappade filobjekt och deras medlemmar.
Uppgift | Metoder eller egenskaper som ska användas |
---|---|
Hämta ett MemoryMappedFile objekt som representerar en sparad minnesmappad fil från en fil på disk. | MemoryMappedFile.CreateFromFile Metod. |
Hämta ett MemoryMappedFile objekt som representerar en minnesmappad fil som inte finns kvar (inte associerad med en fil på disk). | MemoryMappedFile.CreateNew Metod. - eller - MemoryMappedFile.CreateOrOpen Metod. |
För att hämta ett MemoryMappedFile objekt i en befintlig minnesmappad fil (antingen beständiga eller icke-bevarade). | MemoryMappedFile.OpenExisting Metod. |
Hämta ett UnmanagedMemoryStream objekt för en sekventiellt åtkopplad vy till den minnesmappade filen. | MemoryMappedFile.CreateViewStream Metod. |
Hämta ett UnmanagedMemoryAccessor objekt för en slumpmässig åtkomstvy till en minnesmappad fil. | MemoryMappedFile.CreateViewAccessor Metod. |
Hämta ett SafeMemoryMappedViewHandle objekt som ska användas med ohanterad kod. | MemoryMappedFile.SafeMemoryMappedFileHandle Egenskapen. - eller - MemoryMappedViewAccessor.SafeMemoryMappedViewHandle Egenskapen. - eller - MemoryMappedViewStream.SafeMemoryMappedViewHandle Egenskapen. |
Om du vill fördröja allokeringen av minne tills en vy har skapats (endast icke-bevarade filer). (Använd egenskapen för att fastställa den aktuella systemsidans Environment.SystemPageSize storlek.) |
CreateNew metoden med värdet MemoryMappedFileOptions.DelayAllocatePages . - eller - CreateOrOpen metoder som har en MemoryMappedFileOptions uppräkning som en parameter. |
Säkerhet
Du kan använda åtkomsträttigheter när du skapar en minnesmappad fil med hjälp av följande metoder som tar en MemoryMappedFileAccess uppräkning som en parameter:
Du kan ange åtkomsträttigheter för att öppna en befintlig minnesmappad fil med hjälp av de OpenExisting metoder som använder en MemoryMappedFileRights som parameter.
Dessutom kan du inkludera ett MemoryMappedFileSecurity objekt som innehåller fördefinierade åtkomstregler.
Använd metoden för att tillämpa nya eller ändrade åtkomstregler på en minnesmappad fil SetAccessControl . Använd metoden för GetAccessControl att hämta åtkomst- eller granskningsregler från en befintlig fil.
Exempel
Bevarade minnesmappade filer
Metoderna CreateFromFile skapar en minnesmappad fil från en befintlig fil på disken.
I följande exempel skapas en minnesmappad vy av en del av en extremt stor fil och en del av den manipuleras.
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
long offset = 0x10000000; // 256 megabytes
long length = 0x20000000; // 512 megabytes
// Create the memory-mapped file.
using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))
{
// Create a random access view, from the 256th megabyte (the offset)
// to the 768th megabyte (the offset plus length).
using (var accessor = mmf.CreateViewAccessor(offset, length))
{
int colorSize = Marshal.SizeOf(typeof(MyColor));
MyColor color;
// Make changes to the view.
for (long i = 0; i < length; i += colorSize)
{
accessor.Read(i, out color);
color.Brighten(10);
accessor.Write(i, ref color);
}
}
}
}
}
public struct MyColor
{
public short Red;
public short Green;
public short Blue;
public short Alpha;
// Make the view brighter.
public void Brighten(short value)
{
Red = (short)Math.Min(short.MaxValue, (int)Red + value);
Green = (short)Math.Min(short.MaxValue, (int)Green + value);
Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Class Program
Sub Main()
Dim offset As Long = &H10000000 ' 256 megabytes
Dim length As Long = &H20000000 ' 512 megabytes
' Create the memory-mapped file.
Using mmf = MemoryMappedFile.CreateFromFile("c:\ExtremelyLargeImage.data", FileMode.Open, "ImgA")
' Create a random access view, from the 256th megabyte (the offset)
' to the 768th megabyte (the offset plus length).
Using accessor = mmf.CreateViewAccessor(offset, length)
Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))
Dim color As MyColor
Dim i As Long = 0
' Make changes to the view.
Do While (i < length)
accessor.Read(i, color)
color.Brighten(10)
accessor.Write(i, color)
i += colorSize
Loop
End Using
End Using
End Sub
End Class
Public Structure MyColor
Public Red As Short
Public Green As Short
Public Blue As Short
Public Alpha As Short
' Make the view brighter.
Public Sub Brighten(ByVal value As Short)
Red = CType(Math.Min(Short.MaxValue, (CType(Red, Integer) + value)), Short)
Green = CType(Math.Min(Short.MaxValue, (CType(Green, Integer) + value)), Short)
Blue = CType(Math.Min(Short.MaxValue, (CType(Blue, Integer) + value)), Short)
Alpha = CType(Math.Min(Short.MaxValue, (CType(Alpha, Integer) + value)), Short)
End Sub
End Structure
I följande exempel öppnas samma minnesmappade fil för en annan process.
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
// Assumes another process has created the memory-mapped file.
using (var mmf = MemoryMappedFile.OpenExisting("ImgA"))
{
using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))
{
int colorSize = Marshal.SizeOf(typeof(MyColor));
MyColor color;
// Make changes to the view.
for (long i = 0; i < 1500000; i += colorSize)
{
accessor.Read(i, out color);
color.Brighten(20);
accessor.Write(i, ref color);
}
}
}
}
}
public struct MyColor
{
public short Red;
public short Green;
public short Blue;
public short Alpha;
// Make the view brigher.
public void Brighten(short value)
{
Red = (short)Math.Min(short.MaxValue, (int)Red + value);
Green = (short)Math.Min(short.MaxValue, (int)Green + value);
Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
}
}
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Class Program
Public Shared Sub Main(ByVal args As String())
' Assumes another process has created the memory-mapped file.
Using mmf = MemoryMappedFile.OpenExisting("ImgA")
Using accessor = mmf.CreateViewAccessor(4000000, 2000000)
Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))
Dim color As MyColor
' Make changes to the view.
Dim i As Long = 0
While i < 1500000
accessor.Read(i, color)
color.Brighten(30)
accessor.Write(i, color)
i += colorSize
End While
End Using
End Using
End Sub
End Class
Public Structure MyColor
Public Red As Short
Public Green As Short
Public Blue As Short
Public Alpha As Short
' Make the view brigher.
Public Sub Brighten(ByVal value As Short)
Red = CShort(Math.Min(Short.MaxValue, CInt(Red) + value))
Green = CShort(Math.Min(Short.MaxValue, CInt(Green) + value))
Blue = CShort(Math.Min(Short.MaxValue, CInt(Blue) + value))
Alpha = CShort(Math.Min(Short.MaxValue, CInt(Alpha) + value))
End Sub
End Structure
Icke-bevarade minnesmappade filer
Metoderna CreateNew och CreateOrOpen skapar en minnesmappad fil som inte är mappad till en befintlig fil på disken.
Följande exempel består av tre separata processer (konsolprogram) som skriver booleska värden till en minnesmappad fil. Följande sekvens av åtgärder inträffar:
Process A
skapar den minnesmappade filen och skriver ett värde till den.Process B
öppnar den minnesmappade filen och skriver ett värde till den.Process C
öppnar den minnesmappade filen och skriver ett värde till den.Process A
läser och visar värdena från den minnesmappade filen.När
Process A
den minnesmappade filen har slutförts återtas filen omedelbart av skräpinsamlingen.
Kör det här exemplet genom att göra följande:
Kompilera programmen och öppna tre kommandotolksfönster.
I det första kommandotolken kör du
Process A
.I det andra kommandotolken kör du
Process B
.Gå tillbaka till
Process A
och tryck på RETUR.I det tredje kommandotolken kör du
Process C
.Gå tillbaka till
Process A
och tryck på RETUR.
Utdata för Process A
är följande:
Start Process B and press ENTER to continue.
Start Process C and press ENTER to continue.
Process A says: True
Process B says: False
Process C says: True
Bearbeta A
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process A:
static void Main(string[] args)
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))
{
bool mutexCreated;
Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(1);
}
mutex.ReleaseMutex();
Console.WriteLine("Start Process B and press ENTER to continue.");
Console.ReadLine();
Console.WriteLine("Start Process C and press ENTER to continue.");
Console.ReadLine();
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("Process A says: {0}", reader.ReadBoolean());
Console.WriteLine("Process B says: {0}", reader.ReadBoolean());
Console.WriteLine("Process C says: {0}", reader.ReadBoolean());
}
mutex.ReleaseMutex();
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process A:
Sub Main()
Using mmf As MemoryMappedFile = MemoryMappedFile.CreateNew("testmap", 10000)
Dim mutexCreated As Boolean
Dim mTex As Mutex = New Mutex(True, "testmapmutex", mutexCreated)
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(1)
End Using
mTex.ReleaseMutex()
Console.WriteLine("Start Process B and press ENTER to continue.")
Console.ReadLine()
Console.WriteLine("Start Process C and press ENTER to continue.")
Console.ReadLine()
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()
Dim reader As BinaryReader = New BinaryReader(Stream)
Console.WriteLine("Process A says: {0}", reader.ReadBoolean())
Console.WriteLine("Process B says: {0}", reader.ReadBoolean())
Console.WriteLine("Process C says: {0}", reader.ReadBoolean())
End Using
mTex.ReleaseMutex()
End Using
End Sub
End Module
Process B
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process B:
static void Main(string[] args)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
Mutex mutex = Mutex.OpenExisting("testmapmutex");
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(0);
}
mutex.ReleaseMutex();
}
}
catch (FileNotFoundException)
{
Console.WriteLine("Memory-mapped file does not exist. Run Process A first.");
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process B:
Sub Main()
Try
Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")
Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(1, 0)
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(0)
End Using
mTex.ReleaseMutex()
End Using
Catch noFile As FileNotFoundException
Console.WriteLine("Memory-mapped file does not exist. Run Process A first." & vbCrLf & noFile.Message)
End Try
End Sub
End Module
Process C
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process C:
static void Main(string[] args)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
Mutex mutex = Mutex.OpenExisting("testmapmutex");
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream(2, 0))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(1);
}
mutex.ReleaseMutex();
}
}
catch (FileNotFoundException)
{
Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B.");
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process C:
Sub Main()
Try
Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")
Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(2, 0)
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(1)
End Using
mTex.ReleaseMutex()
End Using
Catch noFile As FileNotFoundException
Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B." & vbCrLf & noFile.Message)
End Try
End Sub
End Module