Soubory mapované paměti

Obsah souboru virtuální paměti obsahuje soubor mapovaný v 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. Začínající .NET Framework verze 4, můžete použít spravovaný kód přístup mapovaný do paměti soubory stejným způsobem jako nativní Windows funkce popsané v přístupu k soubory mapované v paměti Managing Memory-Mapped soubory v systému Win32 v knihovně MSDN.

Existují dva typy souborů mapované paměti:

  • Trvalé soubory mapované paměti

    Trvalé soubory jsou soubory mapované paměti, které jsou přidruženy ke zdrojovému souboru na disku. Když poslední proces dokončí práci se souborem, data jsou uložena do zdrojového souboru na disk. Tyto soubory mapované paměti jsou vhodné pro práci s extrémně velkými zdrojovými soubory.

  • Netrvalé soubory mapované paměti

    Netrvalé soubory jsou soubory mapované paměti, které nejsou přidruženy ke zdrojovému souboru na disku. Po dokončení práce se souborem poslední procesu, dojde ke ztrátě dat a je soubor převzaty systémem pro úklid. Tyto soubory jsou vhodné pro vytváření sdílené paměti pro meziprocesovou komunikaci (IPC).

Procesy, zobrazení a správa paměti

Soubory mapované paměti mohou být sdíleny více procesy. Procesy lze namapovat na stejný soubor mapované paměti použitím běžného názvu, který je přiřazen procesem, který vytvořil soubor.

Chcete-li pracovat se soubor mapované paměti, je nutné vytvořit zobrazení celého souboru mapované paměti nebo jeho části. Můžete také vytvořit více zobrazení do stejné části souboru mapované paměti a tím vytvářit souběžnou paměť. Aby dvě zobrazení zůstaly souběžné, musí být vytvořeny ze stejného souboru mapované paměti.

Více zobrazení může být také nezbytné, pokud je soubor větší než velikost logické paměti aplikace, která je k dispozici pro mapování paměti (2 GB pro 32bitové počítače).

Existují dva typy zobrazení: zobrazení datového proudu a zobrazení s náhodným přístupem. Použijte zobrazení datových proudů pro sekvenční přístup k souboru. Toto je doporučeno pro netrvalé soubory a meziprocesovou komunikaci. Zobrazení s náhodným přístupem jsou upřednostňovány pro práci s trvalými soubory.

K souborům mapované paměti je přistupováno prostřednictvím správce paměti operačního systému tak, aby soubor byl automaticky rozdělen do několika stránek, a aby k němu bylo přístupováno podle potřeby. Nemusíte sami zpracovávat správu paměti.

Následující ilustrace znázorňuje, jak více procesů může mít vícenásobné a překrývající se zobrazení stejného souboru mapované paměti ve stejnou dobu.

Vícenásobné a překrývající se zobrazení souboru mapované v paměti

Zobrazení náhledů do souboru namapovaného do paměti

Programování se soubory mapované paměti

Následující tabulka poskytuje návod pro používání objektů souboru mapované paměti a jejich členů.

Úloha

Metody nebo vlastnosti pro použití

Pro získání objektu MemoryMappedFile, který představuje trvalý soubor mapované paměti, ze souboru na disku.

Metoda MemoryMappedFile.CreateFromFile.

Pro získání objektu MemoryMappedFile, který představuje netrvalý soubor mapované paměti (není přidružen k souboru na disku).

Metoda MemoryMappedFile.CreateNew.

-nebo-

Metoda MemoryMappedFile.CreateOrOpen.

Pro získání objektu MemoryMappedFile existujícího souboru mapované paměti (trvalého nebo netrvalého).

Metoda MemoryMappedFile.OpenExisting.

Pro získání objektu UnmanagedMemoryStream pro sekvenční přístup k zobrazení souboru mapované paměti.

Metoda MemoryMappedFile.CreateViewStream.

Pro získání objektu UnmanagedMemoryAccessor pro náhodný přístup k zobrazení souboru mapované paměti.

Metoda MemoryMappedFile.CreateViewAccessor.

Pro získání objektu SafeMemoryMappedViewHandle, který chcete použít s nespravovaným kódem.

MemoryMappedFile.SafeMemoryMappedFileHandleVlastnost.

-nebo-

Vlastnost MemoryMappedViewAccessor.SafeMemoryMappedViewHandle.

-nebo-

MemoryMappedViewStream.SafeMemoryMappedViewHandleVlastnost.

Pro spoždění přidělování paměti až do vytvoření zobrazení (pouze netrvalé soubory).

(Pro určení aktuální velikosti stránky systému, použijte vlastnost Environment.SystemPageSize.)

Metoda CreateNew s hodnotou MemoryMappedFileOptions.DelayAllocatePages.

-nebo-

Metody CreateOrOpen, které mají výčet MemoryMappedFileOptions jako parametr.

Zabezpečení

Můžete použít přístupová práva, když vytvoříte soubor mapované paměti, pomocí následujících metod, které přijímají výčet MemoryMappedFileAccess jako parametr:

Můžete určit přístupová práva pro otevření existujícího souboru mapované paměti použitím metod OpenExisting, které přijmou MemoryMappedFileRights jako parametr.

Kromě toho můžete také zahrnout objekt MemoryMappedFileSecurity, který obsahuje předdefinovaná pravidla přístupu.

Pro použití nových nebo upravených pravidel přístupu k souboru mapované paměti, použijte metodu SetAccessControl. Pro získání pravidel přístupu nebo auditu z existujícího souboru použijte metodu GetAccessControl.

Příklady

Trvalé soubory mapované paměti

Metody CreateFromFile vytvoří soubor mapované paměti z existujícího souboru na disku.

Následující příklad vytvoří zobrazení mapované paměti části extémně velkého souboru a manipuluje s jeho částí.

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)
                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
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 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);
        }
    }

}

Následující příklad otevře stejný soubor mapované paměti pro jiný proces.

Imports System
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
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);
    }
}

Netrvalé soubory mapované paměti

Metody CreateNew a CreateOrOpen vytvoří soubor mapované paměti, který není mapován na existující soubor na disku.

Následující příklad se skládá ze tří oddělených procesů (konzolových aplikací), které zapisují logické hodnoty do souboru mapované paměti. Dojde k následující sekvenci činností:

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

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

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

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

  5. Když Process A ukončí práci se souborem mapované paměti, soubor je okamžitě uvolněn systémem pro uvolnění paměti.

Pro spuštění tohoto příkladu proveďte následující:

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

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

  3. Ve druhém okně příkazového řádku spusťte Process B.

  4. Vraťte se do Process A a stiskněte klávesu ENTER.

  5. Ve třetím okně příkazového řádku spusťte Process C.

  6. Vraťte se do Process A a stiskněte klávesu 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

Proces A

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
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();
        }
    }
}

Proces B

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
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.");
        }
    }
}

Proces C

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
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.");
        }
    }
}

Viz také

Další zdroje

Soubor a proud vstupy