Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Plik mapowany na pamięć zawiera zawartość pliku w pamięci wirtualnej. Ta mapa między plikiem a przestrzenią pamięci umożliwia aplikacji, w tym wielu procesów, modyfikowanie pliku przez odczytywanie i zapisywanie bezpośrednio do pamięci. Za pomocą kodu zarządzanego można uzyskać dostęp do plików mapowanych w pamięci w taki sam sposób, jak natywne funkcje systemu Windows uzyskują dostęp do plików mapowanych w pamięci, zgodnie z opisem w temacie Zarządzanie plikami Memory-Mapped.
Istnieją dwa typy plików mapowanych na pamięć:
Trwałe pliki mapowane na pamięć
Utrwalone pliki to pliki mapowane w pamięci, które są skojarzone z plikiem źródłowym na dysku. Po zakończeniu ostatniego procesu pracy z plikiem dane są zapisywane w pliku źródłowym na dysku. Te pliki mapowane na pamięć są odpowiednie do pracy z bardzo dużymi plikami źródłowymi.
Nietrwałe pliki mapowane na pamięć
Pliki niemapowane na dysku to pliki mapowane na pamięć, które nie są skojarzone z plikiem na dysku. Gdy ostatni proces zakończy pracę z plikiem, dane zostają utracone, a plik jest odzyskiwany przez mechanizm zbierania śmieci. Te pliki są odpowiednie do tworzenia pamięci udostępnionej na potrzeby komunikacji między procesami (IPC).
Procesy, widoki i zarządzanie pamięcią
Pliki mapowane w pamięci mogą być współużytkowane przez wiele procesów. Procesy mogą mapować do tego samego pliku mapowanego na pamięć przy użyciu wspólnej nazwy nadanej przez proces, który utworzył plik.
Aby pracować z plikiem mapowanym na pamięć, należy utworzyć widok całego pliku mapowanego na pamięć lub jego część. Można również utworzyć wiele widoków w tej samej części pliku mapowanego na pamięć, co umożliwia jednoczesny dostęp do pamięci. Aby dwa widoki pozostały współbieżne, należy je utworzyć na podstawie tego samego pliku mapowanego na pamięć.
Wiele widoków może być również konieczne, jeśli plik jest większy niż rozmiar pamięci logicznej aplikacji dostępnej do mapowania pamięci (2 GB na komputerze 32-bitowym).
Istnieją dwa typy widoków: widok dostępu do strumienia i widok dostępu losowego. Użyj widoków dostępu strumieniowego, aby uzyskać dostęp sekwencyjny do pliku; jest to zalecane w przypadku plików nieutrwalonych i IPC. Widoki dostępu losowego są preferowane do pracy z zapisanymi plikami.
Dostęp do plików mapowanych w pamięci jest uzyskiwany za pośrednictwem menedżera pamięci systemu operacyjnego, więc plik jest automatycznie partycjonowany na wiele stron i uzyskiwany do tego dostępu zgodnie z potrzebami. Nie musisz samodzielnie obsługiwać zarządzania pamięcią.
Na poniższej ilustracji pokazano, jak wiele procesów może mieć wiele widoków, w tym nakładających się widoków, na ten sam plik mapowany w pamięci jednocześnie.
Na poniższej ilustracji przedstawiono wiele nachodzących na siebie widoków na plik mapowany na pamięć.
Programowanie przy użyciu plików Memory-Mapped
Poniższa tabela zawiera przewodnik dotyczący używania obiektów plików mapowanych w pamięci i ich elementów członkowskich.
| Zadanie | Metody lub właściwości do użycia |
|---|---|
| Aby uzyskać MemoryMappedFile obiekt reprezentujący utrwalonego pliku mapowanego na pamięć z pliku na dysku. | MemoryMappedFile.CreateFromFile metoda. |
| Aby uzyskać MemoryMappedFile obiekt reprezentujący nietrwały plik mapowany na pamięć (niezwiązany z plikiem na dysku). |
MemoryMappedFile.CreateNew metoda. - lub - MemoryMappedFile.CreateOrOpen metoda. |
| Aby uzyskać MemoryMappedFile obiekt istniejącego pliku mapowanego na pamięć (utrwalonego lub nietrwałego). | MemoryMappedFile.OpenExisting metoda. |
| Aby uzyskać obiekt UnmanagedMemoryStream dla widoku pliku mapowanego na pamięć z sekwencyjnym dostępem. | MemoryMappedFile.CreateViewStream metoda. |
| Aby uzyskać UnmanagedMemoryAccessor obiekt dla widoku dostępu losowego do pliku mapowanego na pamięć. | MemoryMappedFile.CreateViewAccessor metoda. |
| Aby uzyskać obiekt SafeMemoryMappedViewHandle do użycia z kodem niezarządzanym. |
MemoryMappedFile.SafeMemoryMappedFileHandle właściwość. - lub - MemoryMappedViewAccessor.SafeMemoryMappedViewHandle właściwość. - lub - MemoryMappedViewStream.SafeMemoryMappedViewHandle właściwość. |
| Aby opóźnić przydzielanie pamięci do czasu utworzenia widoku (dotyczy tylko plików tymczasowych). (Aby określić bieżący rozmiar strony systemowej, użyj Environment.SystemPageSize właściwości ). |
Metoda CreateNew z wartością MemoryMappedFileOptions.DelayAllocatePages. - lub - CreateOrOpen metody, które mają MemoryMappedFileOptions enumerację jako parametr. |
Bezpieczeństwo
Prawa dostępu można zastosować podczas tworzenia pliku mapowanego w pamięci za pomocą metod przyjmujących enum MemoryMappedFileAccess jako parametr.
Możesz określić prawa dostępu do otwierania istniejącego pliku mapowanego pamięci przy użyciu OpenExisting metod, które przyjmują MemoryMappedFileRights jako parametr.
Ponadto można uwzględnić MemoryMappedFileSecurity obiekt zawierający wstępnie zdefiniowane reguły dostępu.
Aby zastosować nowe lub zmienione reguły dostępu do pliku mapowanego na pamięć, użyj SetAccessControl metody . Aby pobrać reguły dostępu lub inspekcji z istniejącego pliku, użyj GetAccessControl metody .
Przykłady
Utrwalone pliki Memory-Mapped
Metody CreateFromFile tworzą plik mapowany na pamięć z istniejącego pliku na dysku.
Poniższy przykład tworzy mapowany w pamięci widok części bardzo dużego pliku i manipuluje jego fragmentem.
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
W poniższym przykładzie zostanie otwarty ten sam plik mapowany na pamięć dla innego procesu.
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
Nieutrwalone pliki Memory-Mapped
Metody CreateNew i CreateOrOpen tworzą plik mapowany na pamięć, który nie jest mapowany na istniejący plik na dysku.
Poniższy przykład składa się z trzech oddzielnych procesów (aplikacji konsolowych), które zapisują wartości logiczne do pliku zmapowanego w pamięci. Następuje następująca sekwencja akcji:
Process ATworzy plik mapowany na pamięć i zapisuje do niego wartość.Process BOtwiera plik mapowany na pamięć i zapisuje do niego wartość.Process COtwiera plik mapowany na pamięć i zapisuje do niego wartość.Process Aodczytuje i wyświetla wartości z pliku mapowanego w pamięci.Po
Process Azakończeniu pracy z plikiem zamapowanym na pamięć, plik jest natychmiast odzyskiwany przez odśmiecanie pamięci.
Aby uruchomić ten przykład, wykonaj następujące czynności:
Skompiluj aplikacje i otwórz trzy okna wiersza polecenia.
W pierwszym oknie wiersza polecenia uruchom polecenie
Process A.W drugim oknie wiersza polecenia uruchom polecenie
Process B.Wróć do
Process Ai naciśnij ENTER.W trzecim oknie wiersza polecenia uruchom polecenie
Process C.Wróć do
Process Ai naciśnij ENTER.
Dane wyjściowe funkcji Process A są następujące:
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
Proces 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: {reader.ReadBoolean()}");
Console.WriteLine($"Process B says: {reader.ReadBoolean()}");
Console.WriteLine($"Process C says: {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
Proces 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
Proces 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