Soubory mapované paměti

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ů mapovaných pamětí.

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í posledního procesu práce se souborem dojde ke ztrátě dat a uvolnění souboru uvolněním paměti. 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 se souborem mapovanými do paměti, musíte vytvořit zobrazení celého souboru mapovaného paměti 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í se vytvořit ze stejného souboru mapovaného paměti.

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žití zobrazení přístupu ke streamu pro sekvenční přístup k souboru; to se doporučuje pro neudržované 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 může mít více procesů více zobrazení a překrývajících se zobrazení do stejného souboru namapovaného na paměť současně.

Následující obrázek ukazuje více zobrazení a překrývajících se zobrazení do souboru mapovaného do paměti:

Screenshot that shows views to a memory-mapped file.

Programování s mapovanými soubory paměti

Následující tabulka obsahuje průvodce používáním objektů souborů mapovaných v paměti a jejich členů.

Úloha 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 neuchované soubor mapované paměti (není přidružen k souboru na disku). MemoryMappedFile.CreateNew Metoda.

- nebo -

MemoryMappedFile.CreateOrOpen Metoda.
MemoryMappedFile Získání objektu existujícího souboru mapovaného paměti (trvalé nebo neudržované). MemoryMappedFile.OpenExisting Metoda.
Získání objektu UnmanagedMemoryStream pro sekvenční zobrazení k souboru mapovanému paměti. MemoryMappedFile.CreateViewStream Metoda.
Získání objektu UnmanagedMemoryAccessor pro náhodné zobrazení přístupu k souboru mapovanému paměti. 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 výčet jako parametr.

Zabezpečení

Přístupová práva můžete použít při vytváření souboru mapovaného paměti 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 mapované do paměti

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

Neudržované soubory mapované do paměti

CreateOrOpen Metody CreateNew vytvoří soubor mapovaný v paměti, který není namapován na existující soubor 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í:

  1. Process A vytvoří soubor mapovaný do paměti a zapíše do něj hodnotu.

  2. Process B otevře soubor mapovaný do paměti a zapíše do něj hodnotu.

  3. Process C otevře soubor mapovaný do paměti a zapíše do něj hodnotu.

  4. Process A přečte a zobrazí hodnoty ze souboru mapovaného paměti.

  5. Jakmile Process A se soubor mapovaný do paměti dokončí, okamžitě se uvolní uvolňováním paměti.

Pokud chcete tento příklad spustit, postupujte takto:

  1. Zkompilujte aplikace a otevřete tři okna příkazového řádku.

  2. V prvním okně příkazového řádku spusťte Process Apříkaz .

  3. V druhém okně příkazového řádku spusťte Process Bpříkaz .

  4. Vraťte se a Process A stiskněte ENTER.

  5. V třetím okně příkazového řádku spusťte Process Cpříkaz .

  6. Vraťte se a Process A 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: {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

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

Viz také