Bellek eşlemeli dosyalar

Belleğe eşlenen dosya, sanal bellekteki bir dosyanın içeriğini içerir. Bir dosya ve bellek alanı arasındaki bu eşleme, birden çok işlem de dahil olmak üzere bir uygulamanın doğrudan belleğe okuyup yazarak dosyayı değiştirmesine olanak tanır. Yönetilen kodu, bellekle eşlenen dosyalara yerel Windows işlevlerinin bellekle eşlenen dosyalara eriştikleri şekilde erişmek için Bellekle Eşlenen Dosyaları Yönetme bölümünde açıklandığı gibi kullanabilirsiniz.

İki tür belleğe eşlenmiş dosya vardır:

  • Kalıcı belleğe eşlenmiş dosyalar

    Kalıcı dosyalar, disk üzerindeki bir kaynak dosyayla ilişkili belleğe eşlenmiş dosyalardır. Son işlem dosyayla çalışmayı bitirdiğinde, veriler disk üzerindeki kaynak dosyaya kaydedilir. Bu bellek eşlemeli dosyalar, son derece büyük kaynak dosyalarla çalışmak için uygundur.

  • Kalıcı olmayan bellek eşlemeli dosyalar

    Kalıcı olmayan dosyalar, disk üzerindeki bir dosyayla ilişkilendirilmemiş bellekle eşlenen dosyalardır. Son işlem dosyayla çalışmayı bitirdiğinde, veriler kaybolur ve dosya çöp toplama tarafından geri kazanılır. Bu dosyalar, işlemler arası iletişimler (IPC) için paylaşılan bellek oluşturmak için uygundur.

İşlemler, Görünümler ve Belleği Yönetme

Bellekle eşlenen dosyalar birden çok işlem arasında paylaşılabilir. İşlemler, dosyayı oluşturan işlem tarafından atanan ortak bir ad kullanarak aynı bellek eşleme dosyasına eşlenebilir.

Bellekle eşlenen bir dosyayla çalışmak için, bellekle eşlenen dosyanın tamamının veya bir bölümünün görünümünü oluşturmanız gerekir. Ayrıca, bellekle eşlenen dosyanın aynı bölümünde birden çok görünüm oluşturabilir ve böylece eşzamanlı bellek oluşturabilirsiniz. İki görünümün eşzamanlı kalması için bunların aynı bellekle eşlenen dosyadan oluşturulması gerekir.

Dosya, bellek eşlemesi için kullanılabilir mantıksal bellek alanının boyutundan büyükse (32 bit bilgisayarda 2 GB) birden çok görünüm de gerekebilir.

İki tür görünüm vardır: akış erişim görünümü ve rastgele erişim görünümü. Bir dosyaya sıralı erişim için akış erişim görünümlerini kullanma; bu, kalıcı olmayan dosyalar ve IPC için önerilir. Kalıcı dosyalarla çalışmak için rastgele erişim görünümleri tercih edilir.

Belleğe eşlenen dosyalara işletim sisteminin bellek yöneticisi aracılığıyla erişilir, bu nedenle dosya otomatik olarak birkaç sayfaya bölümlenir ve gerektiğinde erişilir. Bellek yönetimini kendiniz işlemeniz gerekmez.

Aşağıdaki çizimde, birden çok işlemin aynı anda aynı bellekle eşlenen dosyaya nasıl birden çok ve çakışan görünüme sahip olabileceği gösterilmektedir.

Aşağıdaki görüntüde, bellekle eşlenmiş bir dosyaya birden çok ve çakışan görünüm gösterilir:

Screenshot that shows views to a memory-mapped file.

Bellek Eşlemeli Dosyalarla Programlama

Aşağıdaki tabloda, bellekle eşlenen dosya nesnelerini ve bunların üyelerini kullanmaya yönelik bir kılavuz sağlanır.

Görev Kullanılacak yöntemler veya özellikler
Disk üzerindeki bir MemoryMappedFile dosyadan kalıcı belleğe eşlenmiş bir dosyayı temsil eden bir nesne elde etmek için. MemoryMappedFile.CreateFromFile Yöntem.
Kalıcı olmayan bellek eşlemeli bir MemoryMappedFile dosyayı (disk üzerindeki bir dosyayla ilişkilendirilmemiş) temsil eden bir nesne elde etmek için. MemoryMappedFile.CreateNew Yöntem.

- veya -

MemoryMappedFile.CreateOrOpen Yöntem.
Var olan bellekle eşlenmiş bir MemoryMappedFile dosyanın nesnesini almak için (kalıcı veya kalıcı değil). MemoryMappedFile.OpenExisting Yöntem.
Belleğe eşlenen dosyaya sıralı olarak erişilen bir görünüme yönelik bir nesne elde UnmanagedMemoryStream etmek için. MemoryMappedFile.CreateViewStream Yöntem.
Belleğe eşlenmiş bir UnmanagedMemoryAccessor dosyaya rastgele erişim görünümüne yönelik bir nesne elde etmek için. MemoryMappedFile.CreateViewAccessor Yöntem.
Yönetilmeyen kodla kullanılacak bir SafeMemoryMappedViewHandle nesne elde etmek için. MemoryMappedFile.SafeMemoryMappedFileHandle Özellik.

- veya -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle Özellik.

- veya -

MemoryMappedViewStream.SafeMemoryMappedViewHandle Özellik.
Bir görünüm oluşturulana kadar bellek ayırmayı geciktirmek için (yalnızca kalıcı olmayan dosyalar).

(Geçerli sistem sayfa boyutunu belirlemek için özelliğini kullanın Environment.SystemPageSize .)
CreateNew yöntemine MemoryMappedFileOptions.DelayAllocatePages tıklayın.

- veya -

CreateOrOpen parametre olarak bir MemoryMappedFileOptions numaralandırması olan yöntemler.

Güvenlik

Bir numaralandırmayı parametre olarak alan MemoryMappedFileAccess aşağıdaki yöntemleri kullanarak bellekle eşlenmiş bir dosya oluşturduğunuzda erişim hakları uygulayabilirsiniz:

Parametre olarak alan MemoryMappedFileRights yöntemleri kullanarak OpenExisting mevcut bellek eşlemeli dosyayı açmak için erişim hakları belirtebilirsiniz.

Ayrıca, önceden tanımlanmış erişim kuralları içeren bir MemoryMappedFileSecurity nesne de ekleyebilirsiniz.

Bellekle eşlenen bir dosyaya yeni veya değiştirilmiş erişim kuralları uygulamak için yöntemini kullanın SetAccessControl . Mevcut bir dosyadan erişim veya denetim kuralları almak için yöntemini kullanın GetAccessControl .

Örnekler

Kalıcı Belleğe Eşlenmiş Dosyalar

Yöntemler, CreateFromFile diskte var olan bir dosyadan belleğe eşlenmiş bir dosya oluşturur.

Aşağıdaki örnek, son derece büyük bir dosyanın bir bölümünün belleğe eşlenmiş bir görünümünü oluşturur ve bir bölümünü işler.

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

Aşağıdaki örnek, başka bir işlem için aynı bellek eşlemeli dosyayı açar.

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

Kalıcı Olmayan Belleğe Eşlenen Dosyalar

CreateNew ve CreateOrOpen yöntemleri, diskte var olan bir dosyaya eşlenmeyen bellekle eşlenmiş bir dosya oluşturur.

Aşağıdaki örnek, belleğe eşlenmiş bir dosyaya Boole değerleri yazan üç ayrı işlemden (konsol uygulamaları) oluşur. Aşağıdaki eylem dizisi gerçekleşir:

  1. Process A bellekle eşlenen dosyayı oluşturur ve dosyaya bir değer yazar.

  2. Process B bellekle eşlenen dosyayı açar ve dosyaya bir değer yazar.

  3. Process C bellekle eşlenen dosyayı açar ve dosyaya bir değer yazar.

  4. Process A bellekle eşlenen dosyadaki değerleri okur ve görüntüler.

  5. Bellekle eşlenen dosyayla tamamlandıktan sonra Process A , dosya çöp toplama tarafından hemen geri kazanılır.

Bu örneği çalıştırmak için aşağıdakileri yapın:

  1. Uygulamaları derleyin ve üç Komut İstemi penceresi açın.

  2. İlk Komut İstemi penceresinde komutunu çalıştırın Process A.

  3. İkinci Komut İstemi penceresinde komutunu çalıştırın Process B.

  4. adresine Process A dönün ve ENTER tuşuna basın.

  5. Üçüncü Komut İstemi penceresinde komutunu çalıştırın Process C.

  6. adresine Process A dönün ve ENTER tuşuna basın.

çıktısı Process A aşağıdaki gibidir:

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  

İşlem 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

İşlem 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

İşlem 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

Ayrıca bkz.