Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Soubor mapovaný do paměti obsahuje obsah souboru ve virtuální paměti. Toto mapování mezi souborem a paměťovým prostorem umožňuje aplikaci, včetně více procesů, upravovat soubor čtením a zápisem přímo do paměti. Spravovaný kód můžete použít pro přístup k souborům mapovaným v paměti stejným způsobem, jakým nativní funkce systému Windows přistupují k souborům mapovaným v paměti, jak je popsáno v tématu Správa souborů Memory-Mapped.
Existují dva typy souborů mapovaných do paměti:
Trvalé soubory mapované do paměti
Trvalé soubory jsou soubory mapované do paměti, které jsou přidruženy ke zdrojovému souboru na disku. Po dokončení posledního procesu práce se souborem se data uloží do zdrojového souboru na disku. Tyto soubory mapované do paměti jsou vhodné pro práci s extrémně velkými zdrojovými soubory.
Neudržované soubory mapované do paměti
Neuchované soubory jsou soubory mapované do paměti, které nejsou přidruženy k souboru na disku. Po dokončení práce posledního procesu se souborem jsou data ztracena a soubor je uvolněn procesem garbage collectoru. Tyto soubory jsou vhodné pro vytvoření sdílené paměti pro komunikaci mezi procesy (IPC).
Procesy, zobrazení a správa paměti
Soubory mapované do paměti je možné sdílet napříč několika procesy. Procesy se můžou mapovat na stejný soubor mapovaný pamětí pomocí běžného názvu, který je přiřazen procesem, který soubor vytvořil.
Pokud chcete pracovat s paměťově mapovaným souborem, musíte vytvořit zobrazení celého paměťově mapovaného souboru nebo jeho části. Můžete také vytvořit více zobrazení do stejné části souboru mapovaného paměti, čímž se vytvoří souběžná paměť. Aby dvě zobrazení zůstala souběžná, musí být vytvořena ze stejného pamětí mapovaného souboru.
Více zobrazení může být také nutné, pokud je soubor větší než velikost místa logické paměti aplikace dostupného pro mapování paměti (2 GB na 32bitovém počítači).
Existují dva typy zobrazení: zobrazení přístupu ke streamu a zobrazení náhodného přístupu. Používejte zobrazení přístupu ke streamu pro sekvenční přístup k souboru. To se doporučuje pro neperzistentní soubory a IPC. Zobrazení náhodného přístupu jsou upřednostňovaná pro práci s trvalými soubory.
K souborům mapovaným v paměti se přistupuje prostřednictvím správce paměti operačního systému, takže se soubor automaticky rozdělí na několik stránek a podle potřeby se k němu přistupuje. Správu paměti nemusíte zpracovávat sami.
Následující obrázek znázorňuje, jak více procesů může mít více zobrazení a překrývající se zobrazení v paměťově namapovaném souboru zároveň.
Následující obrázek ukazuje více zobrazení a překrývajících se zobrazení do souboru mapovaného do paměti:
Programování se soubory Memory-Mapped
Následující tabulka obsahuje průvodce používáním objektů souborů mapovaných v paměti a jejich členů.
| Úkol | Metody nebo vlastnosti, které se mají použít |
|---|---|
| Chcete-li získat MemoryMappedFile objekt, který představuje trvalý soubor mapovaný v paměti ze souboru na disku. | MemoryMappedFile.CreateFromFile Metoda. |
| Chcete-li získat MemoryMappedFile objekt, který představuje neuložený paměťově mapovaný soubor (není spojený se souborem na disku). |
MemoryMappedFile.CreateNew Metoda. - nebo - MemoryMappedFile.CreateOrOpen Metoda. |
| Získání objektu existujícího souboru mapovaného do paměti (trvalého nebo netrvalého). | MemoryMappedFile.OpenExisting Metoda. |
| Chcete-li získat objekt UnmanagedMemoryStream pro sekvenční přístup k zobrazení do paměti mapovanému souboru. | MemoryMappedFile.CreateViewStream Metoda. |
| Získání objektu UnmanagedMemoryAccessor pro náhodný přístup k paměťově mapovanému souboru. | MemoryMappedFile.CreateViewAccessor Metoda. |
| Získání objektu SafeMemoryMappedViewHandle , který se má použít s nespravovaným kódem. |
MemoryMappedFile.SafeMemoryMappedFileHandle vlastnost. - nebo - MemoryMappedViewAccessor.SafeMemoryMappedViewHandle vlastnost. - nebo - MemoryMappedViewStream.SafeMemoryMappedViewHandle vlastnost. |
| Odložení přidělování paměti, dokud se nevytvořilo zobrazení (pouze neuchované soubory). (Chcete-li určit aktuální velikost systémové stránky, použijte Environment.SystemPageSize vlastnost.) |
CreateNew metoda s MemoryMappedFileOptions.DelayAllocatePages hodnotou. - nebo - CreateOrOpen metody, které mají MemoryMappedFileOptions enumeraci jako parametr. |
Zabezpečení
Při vytváření souboru mapovaného do paměti můžete nastavit přístupová práva pomocí následujících metod, které jako parametr berou MemoryMappedFileAccess výčet:
Přístupová práva pro otevření existujícího souboru mapovaného paměti můžete zadat pomocí OpenExisting metod, které jako parametr přebírají MemoryMappedFileRights .
Kromě toho můžete zahrnout MemoryMappedFileSecurity objekt, který obsahuje předdefinovaná pravidla přístupu.
Chcete-li použít nová nebo změněná pravidla přístupu pro soubor mapovaný v paměti, použijte metodu SetAccessControl . Pokud chcete načíst pravidla přístupu nebo auditování z existujícího souboru, použijte metodu GetAccessControl .
Příklady
Trvalé soubory Memory-Mapped
Metody CreateFromFile vytvoří soubor mapovaný do paměti z existujícího souboru na disku.
Následující příklad vytvoří zobrazení mapované paměti části extrémně velkého souboru a manipuluje s jeho částí.
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
Následující příklad otevře stejný soubor mapovaný v paměti pro jiný proces.
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
Neuchované soubory Memory-Mapped
Metody CreateNew a CreateOrOpen vytvoří soubor mapovaný v paměti, který není připojen k existujícímu souboru na disku.
Následující příklad se skládá ze tří samostatných procesů (konzolových aplikací), které zapisují logické hodnoty do souboru mapovaného do paměti. Dochází k následující sekvenci akcí:
Process Avytvoří soubor mapovaný do paměti a zapíše do něj hodnotu.Process Botevře soubor mapovaný do paměti a zapíše do něj hodnotu.Process Cotevře soubor mapovaný do paměti a zapíše do něj hodnotu.Process Apřečte a zobrazí hodnoty ze souboru mapovaného do paměti.Jakmile se soubor mapovaný do paměti
Process Adokončí, okamžitě se uvolní správcem paměti.
Pokud chcete tento příklad spustit, postupujte takto:
Zkompilujte aplikace a otevřete tři okna příkazového řádku.
V prvním okně příkazového řádku spusťte
Process Apříkaz .V druhém okně příkazového řádku spusťte
Process Bpříkaz .Vraťte se
Process Aa stiskněte ENTER.V třetím okně příkazového řádku spusťte
Process Cpříkaz .Vraťte se
Process Aa stiskněte ENTER.
Výstup Process A je následující:
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
Zpracování 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