Delen via


Geheugen toegewezen bestanden

Een geheugentoewijzingsbestand bevat de inhoud van een bestand in het virtuele geheugen. Door deze toewijzing tussen een bestand en geheugenruimte kan een toepassing, inclusief meerdere processen, het bestand wijzigen door het bestand rechtstreeks naar het geheugen te lezen en te schrijven. U kunt beheerde code gebruiken om toegang te krijgen tot door het geheugen toegewezen bestanden op dezelfde manier als systeemeigen Windows-functies toegang krijgen tot geheugen toegewezen bestanden, zoals beschreven in Het beheren van geheugen toegewezen bestanden.

Er zijn twee typen geheugentoewijzingen:

  • Persistente geheugentoewijzingsbestanden

    Persistente bestanden zijn door het geheugen toegewezen bestanden die zijn gekoppeld aan een bronbestand op een schijf. Wanneer het laatste proces met het bestand is voltooid, worden de gegevens opgeslagen in het bronbestand op de schijf. Deze geheugentoewijzingsbestanden zijn geschikt voor het werken met extreem grote bronbestanden.

  • Niet-persistente geheugentoewijzingsbestanden

    Niet-persistente bestanden zijn geheugen toegewezen bestanden die niet zijn gekoppeld aan een bestand op een schijf. Wanneer het laatste proces met het bestand is voltooid, gaan de gegevens verloren en wordt het bestand vrijgemaakt door garbagecollection. Deze bestanden zijn geschikt voor het maken van gedeeld geheugen voor interprocescommunicatie (IPC).

Processen, weergaven en geheugen beheren

Geheugen toegewezen bestanden kunnen worden gedeeld over meerdere processen. Processen kunnen worden toegewezen aan hetzelfde geheugentoewijzingsbestand met behulp van een algemene naam die wordt toegewezen door het proces dat het bestand heeft gemaakt.

Als u wilt werken met een geheugentoewijzingsbestand, moet u een weergave maken van het volledige geheugentoewijzingsbestand of een deel ervan. U kunt ook meerdere weergaven maken naar hetzelfde deel van het geheugentoewijzingsbestand, waardoor gelijktijdig geheugen wordt gemaakt. Twee weergaven blijven gelijktijdig, moeten ze worden gemaakt op basis van hetzelfde geheugentoewijzingsbestand.

Er kunnen ook meerdere weergaven nodig zijn als het bestand groter is dan de grootte van de logische geheugenruimte van de toepassing die beschikbaar is voor geheugentoewijzing (2 GB op een 32-bits computer).

Er zijn twee typen weergaven: streamtoegangsweergave en willekeurige toegangsweergave. Gebruik streamtoegangsweergaven voor sequentiële toegang tot een bestand; dit wordt aanbevolen voor niet-persistente bestanden en IPC. Weergaven voor willekeurige toegang hebben de voorkeur voor het werken met persistente bestanden.

Geheugen toegewezen bestanden worden geopend via het geheugenbeheer van het besturingssysteem, zodat het bestand automatisch wordt gepartitioneerd in een aantal pagina's en indien nodig wordt geopend. U hoeft het geheugenbeheer niet zelf af te handelen.

In de volgende afbeelding ziet u hoe meerdere processen tegelijkertijd meerdere en overlappende weergaven kunnen hebben voor hetzelfde geheugentoewijzingsbestand.

In de volgende afbeelding ziet u meerdere en overlappende weergaven naar een geheugentoewijzingsbestand:

Screenshot that shows views to a memory-mapped file.

Programmeren met geheugentoewijzingsbestanden

De volgende tabel bevat een handleiding voor het gebruik van bestandsobjecten met geheugentoewijzing en hun leden.

Opdracht Methoden of eigenschappen die moeten worden gebruikt
Als u een MemoryMappedFile object wilt ophalen dat een persistent geheugentoewijzingsbestand vertegenwoordigt van een bestand op schijf. MemoryMappedFile.CreateFromFile methode.
Een object ophalen MemoryMappedFile dat een niet-persistent geheugentoewijzingsbestand vertegenwoordigt (niet gekoppeld aan een bestand op schijf). MemoryMappedFile.CreateNew methode.

- of -

MemoryMappedFile.CreateOrOpen methode.
Een object van een bestaand geheugentoewijzingsbestand verkrijgen MemoryMappedFile (persistent of niet-persistent). MemoryMappedFile.OpenExisting methode.
Een object verkrijgen UnmanagedMemoryStream voor een sequentiële toegang tot het geheugentoewijzingsbestand. MemoryMappedFile.CreateViewStream methode.
Een object voor UnmanagedMemoryAccessor een willekeurige toegangsweergave verkrijgen tot een geheugentoewijzingsbestand. MemoryMappedFile.CreateViewAccessor methode.
Een object verkrijgen SafeMemoryMappedViewHandle dat moet worden gebruikt met niet-beheerde code. MemoryMappedFile.SafeMemoryMappedFileHandle Eigenschap.

- of -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle Eigenschap.

- of -

MemoryMappedViewStream.SafeMemoryMappedViewHandle Eigenschap.
Het toewijzen van geheugen vertragen totdat een weergave wordt gemaakt (alleen niet-persistente bestanden).

(Als u het huidige systeempaginaformaat wilt bepalen, gebruikt u de Environment.SystemPageSize eigenschap.)
CreateNew methode met de MemoryMappedFileOptions.DelayAllocatePages waarde.

- of -

CreateOrOpen methoden met een MemoryMappedFileOptions opsomming als parameter.

Beveiliging

U kunt toegangsrechten toepassen wanneer u een geheugentoewijzingsbestand maakt met behulp van de volgende methoden die een MemoryMappedFileAccess opsomming als parameter gebruiken:

U kunt toegangsrechten opgeven voor het openen van een bestaand geheugentoewijzingsbestand met behulp van de OpenExisting methoden die een MemoryMappedFileRights parameter gebruiken.

Daarnaast kunt u een MemoryMappedFileSecurity object opnemen dat vooraf gedefinieerde toegangsregels bevat.

Als u nieuwe of gewijzigde toegangsregels wilt toepassen op een geheugentoewijzingsbestand, gebruikt u de SetAccessControl methode. Gebruik de GetAccessControl methode om toegangs- of controleregels op te halen uit een bestaand bestand.

Voorbeelden

Persistente geheugentoewijzingsbestanden

De CreateFromFile methoden maken een geheugentoewijzingsbestand op basis van een bestaand bestand op schijf.

In het volgende voorbeeld wordt een geheugenweergave gemaakt van een deel van een zeer groot bestand en wordt een deel ervan bewerkt.

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

In het volgende voorbeeld wordt hetzelfde geheugentoewijzingsbestand geopend voor een ander 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

Niet-persistente geheugentoewijzingsbestanden

De CreateNew en CreateOrOpen methoden maken een geheugentoewijzingsbestand dat niet is toegewezen aan een bestaand bestand op schijf.

Het volgende voorbeeld bestaat uit drie afzonderlijke processen (consoletoepassingen) die Booleaanse waarden schrijven naar een bestand dat is toegewezen aan het geheugen. De volgende reeks acties vindt plaats:

  1. Process A maakt het geheugentoewijzingsbestand en schrijft er een waarde naartoe.

  2. Process B opent het geheugentoewijzingsbestand en schrijft er een waarde naartoe.

  3. Process C opent het geheugentoewijzingsbestand en schrijft er een waarde naartoe.

  4. Process A leest de waarden uit het geheugentoewijzingsbestand en geeft deze weer.

  5. Nadat Process A het geheugentoewijzingsbestand is voltooid, wordt het bestand onmiddellijk vrijgemaakt door garbagecollection.

Ga als volgt te werk om dit voorbeeld uit te voeren:

  1. Compileer de toepassingen en open drie opdrachtpromptvensters.

  2. Voer in het eerste opdrachtpromptvenster de opdracht uit Process A.

  3. Voer in het tweede opdrachtpromptvenster de opdracht uit Process B.

  4. Ga terug naar Process A en druk op Enter.

  5. Voer in het derde opdrachtpromptvenster de opdracht uit Process C.

  6. Ga terug naar Process A en druk op Enter.

De uitvoer is Process A als volgt:

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: {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

Zie ook