Dela via


Minnesmappade filer

En minnesmappad fil innehåller innehållet i en fil i det virtuella minnet. Den här mappningen mellan en fil och ett minnesutrymme gör det möjligt för ett program, inklusive flera processer, att ändra filen genom att läsa och skriva direkt till minnet. Du kan använda hanterad kod för att komma åt minnesmappade filer på samma sätt som inbyggda Windows-funktioner får åtkomst till minnesmappade filer, enligt beskrivningen i Hantera minnesmappade filer.

Det finns två typer av minnesmappade filer:

  • Bevarade minnesmappade filer

    Bevarade filer är minnesmappade filer som är associerade med en källfil på en disk. När den senaste processen har slutförts med filen sparas data i källfilen på disken. Dessa minnesmappade filer är lämpliga för att arbeta med extremt stora källfiler.

  • Icke-bevarade minnesmappade filer

    Icke-bevarade filer är minnesmappade filer som inte är associerade med en fil på en disk. När den senaste processen har slutförts med filen går data förlorade och filen återvinns av skräpinsamling. Dessa filer är lämpliga för att skapa delat minne för kommunikation mellan processer (IPC).

Processer, vyer och hantering av minne

Minnesmappade filer kan delas mellan flera processer. Processer kan mappas till samma minnesmappade fil med hjälp av ett gemensamt namn som tilldelas av processen som skapade filen.

Om du vill arbeta med en minnesmappad fil måste du skapa en vy över hela den minnesmappade filen eller en del av den. Du kan också skapa flera vyer till samma del av den minnesmappade filen och därmed skapa samtidigt minne. För att två vyer ska förbli samtidiga måste de skapas från samma minnesmappade fil.

Flera vyer kan också vara nödvändiga om filen är större än storleken på programmets logiska minnesutrymme som är tillgängligt för minnesmappning (2 GB på en 32-bitars dator).

Det finns två typer av vyer: dataströmåtkomstvy och slumpmässig åtkomstvy. Använd dataströmåtkomstvyer för sekventiell åtkomst till en fil. Detta rekommenderas för icke-bevarade filer och IPC. Slumpmässiga åtkomstvyer rekommenderas för att arbeta med bevarade filer.

Minnesmappade filer nås via operativsystemets minneshanterare, så filen partitioneras automatiskt till ett antal sidor och nås efter behov. Du behöver inte hantera minneshanteringen själv.

Följande bild visar hur flera processer kan ha flera och överlappande vyer till samma minnesmappade fil samtidigt.

Följande bild visar flera och överlappande vyer till en minnesmappad fil:

Screenshot that shows views to a memory-mapped file.

Programmering med minnesmappade filer

Följande tabell innehåller en guide för att använda minnesmappade filobjekt och deras medlemmar.

Uppgift Metoder eller egenskaper som ska användas
Hämta ett MemoryMappedFile objekt som representerar en sparad minnesmappad fil från en fil på disk. MemoryMappedFile.CreateFromFile Metod.
Hämta ett MemoryMappedFile objekt som representerar en minnesmappad fil som inte finns kvar (inte associerad med en fil på disk). MemoryMappedFile.CreateNew Metod.

- eller -

MemoryMappedFile.CreateOrOpen Metod.
För att hämta ett MemoryMappedFile objekt i en befintlig minnesmappad fil (antingen beständiga eller icke-bevarade). MemoryMappedFile.OpenExisting Metod.
Hämta ett UnmanagedMemoryStream objekt för en sekventiellt åtkopplad vy till den minnesmappade filen. MemoryMappedFile.CreateViewStream Metod.
Hämta ett UnmanagedMemoryAccessor objekt för en slumpmässig åtkomstvy till en minnesmappad fil. MemoryMappedFile.CreateViewAccessor Metod.
Hämta ett SafeMemoryMappedViewHandle objekt som ska användas med ohanterad kod. MemoryMappedFile.SafeMemoryMappedFileHandle Egenskapen.

- eller -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle Egenskapen.

- eller -

MemoryMappedViewStream.SafeMemoryMappedViewHandle Egenskapen.
Om du vill fördröja allokeringen av minne tills en vy har skapats (endast icke-bevarade filer).

(Använd egenskapen för att fastställa den aktuella systemsidans Environment.SystemPageSize storlek.)
CreateNew metoden med värdet MemoryMappedFileOptions.DelayAllocatePages .

- eller -

CreateOrOpen metoder som har en MemoryMappedFileOptions uppräkning som en parameter.

Säkerhet

Du kan använda åtkomsträttigheter när du skapar en minnesmappad fil med hjälp av följande metoder som tar en MemoryMappedFileAccess uppräkning som en parameter:

Du kan ange åtkomsträttigheter för att öppna en befintlig minnesmappad fil med hjälp av de OpenExisting metoder som använder en MemoryMappedFileRights som parameter.

Dessutom kan du inkludera ett MemoryMappedFileSecurity objekt som innehåller fördefinierade åtkomstregler.

Använd metoden för att tillämpa nya eller ändrade åtkomstregler på en minnesmappad fil SetAccessControl . Använd metoden för GetAccessControl att hämta åtkomst- eller granskningsregler från en befintlig fil.

Exempel

Bevarade minnesmappade filer

Metoderna CreateFromFile skapar en minnesmappad fil från en befintlig fil på disken.

I följande exempel skapas en minnesmappad vy av en del av en extremt stor fil och en del av den manipuleras.

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

I följande exempel öppnas samma minnesmappade fil för en annan process.

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

Icke-bevarade minnesmappade filer

Metoderna CreateNew och CreateOrOpen skapar en minnesmappad fil som inte är mappad till en befintlig fil på disken.

Följande exempel består av tre separata processer (konsolprogram) som skriver booleska värden till en minnesmappad fil. Följande sekvens av åtgärder inträffar:

  1. Process A skapar den minnesmappade filen och skriver ett värde till den.

  2. Process B öppnar den minnesmappade filen och skriver ett värde till den.

  3. Process C öppnar den minnesmappade filen och skriver ett värde till den.

  4. Process A läser och visar värdena från den minnesmappade filen.

  5. När Process A den minnesmappade filen har slutförts återtas filen omedelbart av skräpinsamlingen.

Kör det här exemplet genom att göra följande:

  1. Kompilera programmen och öppna tre kommandotolksfönster.

  2. I det första kommandotolken kör du Process A.

  3. I det andra kommandotolken kör du Process B.

  4. Gå tillbaka till Process A och tryck på RETUR.

  5. I det tredje kommandotolken kör du Process C.

  6. Gå tillbaka till Process A och tryck på RETUR.

Utdata för Process A är följande:

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  

Bearbeta 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

Process 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

Process 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

Se även