Bagikan melalui


File yang dipetakan ke memori

File yang dipetakan ke memori berisi konten dari sebuah file dalam memori virtual. Pemetaan antara file dan ruang memori ini memungkinkan aplikasi, termasuk beberapa proses, untuk memodifikasi file dengan membaca dan menulis langsung ke memori. Anda dapat menggunakan kode terkelola untuk mengakses file yang dipetakan memori dengan cara yang sama seperti fungsi Windows asli mengakses file yang dipetakan memori, seperti yang dijelaskan dalam Mengelola file Memory-Mapped.

Ada dua jenis file yang dipetakan memori:

  • File peta memori yang bertahan

    File yang disimpan secara permanen adalah file memori yang dipetakan yang terkait dengan file sumber di dalam disk. Ketika proses terakhir telah selesai bekerja dengan file, data disimpan ke file sumber pada disk. File yang dipetakan memori ini cocok untuk bekerja dengan file sumber yang sangat besar.

  • File memori yang dipetakan dan tidak bertahan

    File yang tidak bertahan adalah file yang dipetakan memori yang tidak terkait dengan file pada disk. Ketika proses terakhir selesai menggunakan file, data tersebut akan terhapus dan file tersebut diambil alih kembali oleh pengumpulan sampah. File-file ini cocok untuk membuat memori bersama untuk komunikasi antar-proses (IPC).

Proses, Tampilan, dan Pengelolaan Memori

File pemetaan memori dapat digunakan bersama oleh beberapa proses. Proses dapat memetakan ke file yang dipetakan memori yang sama dengan menggunakan nama umum yang ditetapkan oleh proses yang membuat file.

Untuk bekerja dengan file yang dipetakan memori, Anda harus membuat tampilan seluruh file yang dipetakan memori atau bagian darinya. Anda juga dapat membuat beberapa tampilan ke bagian yang sama dari file peta memori, sehingga memungkinkan memori ini diakses secara bersamaan. Agar dua tampilan tetap bersamaan, tampilan harus dibuat dari file yang dipetakan memori yang sama.

Beberapa tampilan mungkin juga diperlukan jika file lebih besar dari ukuran ruang memori logis aplikasi yang tersedia untuk pemetaan memori (2 GB pada komputer 32-bit).

Ada dua jenis tampilan: tampilan akses aliran dan tampilan akses acak. Gunakan tampilan akses aliran untuk akses berurutan ke file; ini direkomendasikan untuk file dan IPC yang tidak bertahan. Penayangan akses acak lebih disukai untuk bekerja dengan file yang disimpan.

File yang dipetakan memori diakses melalui manajer memori sistem operasi, sehingga file secara otomatis dipartisi ke dalam sejumlah halaman dan diakses sesuai kebutuhan. Anda tidak perlu menangani manajemen memori sendiri.

Ilustrasi berikut menunjukkan bagaimana proses-proses dapat memiliki beberapa tampilan yang saling tumpang tindih ke file yang dipetakan ke memori yang sama pada waktu yang bersamaan.

Gambar berikut menunjukkan beberapa tampilan yang saling tumpang tindih ke file yang dipetakan ke memori.

Cuplikan layar yang memperlihatkan tampilan ke file yang dipetakan memori.

Pemrograman dengan File Memory-Mapped

Tabel berikut ini menyediakan panduan untuk menggunakan objek file yang dipetakan memori dan anggotanya.

Tugas Metode atau properti yang akan digunakan
Untuk mendapatkan MemoryMappedFile objek yang mewakili file yang dipetakan memori yang bertahan dari file pada disk. MemoryMappedFile.CreateFromFile metode.
Untuk mendapatkan MemoryMappedFile objek yang mewakili file yang dipetakan memori yang tidak bertahan (tidak terkait dengan file pada disk). MemoryMappedFile.CreateNew metode.

- atau -

MemoryMappedFile.CreateOrOpen metode.
Untuk mendapatkan objek MemoryMappedFile dari file yang dipetakan memori yang sudah ada (baik yang bersifat persisten maupun tidak persisten). MemoryMappedFile.OpenExisting metode.
Untuk mendapatkan UnmanagedMemoryStream objek untuk tampilan yang diakses secara berurutan ke file yang dipetakan ke memori. MemoryMappedFile.CreateViewStream metode.
Untuk mendapatkan UnmanagedMemoryAccessor objek untuk tampilan akses acak ke file yang dipetakan memori. MemoryMappedFile.CreateViewAccessor metode.
Untuk mendapatkan objek SafeMemoryMappedViewHandle untuk digunakan dengan kode yang tidak dikelola. MemoryMappedFile.SafeMemoryMappedFileHandle properti.

- atau -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle properti.

- atau -

MemoryMappedViewStream.SafeMemoryMappedViewHandle properti.
Untuk menunda alokasi memori hingga tampilan dibuat (file yang tidak bertahan saja).

(Untuk menentukan ukuran halaman sistem saat ini, gunakan Environment.SystemPageSize properti .)
CreateNew metode dengan MemoryMappedFileOptions.DelayAllocatePages nilai .

- atau -

CreateOrOpen metode yang memiliki MemoryMappedFileOptions enumerasi sebagai parameter.

Keamanan

Anda dapat menerapkan hak akses saat membuat file yang dipetakan memori, dengan menggunakan metode berikut yang mengambil MemoryMappedFileAccess enumerasi sebagai parameter:

Anda dapat menentukan hak akses untuk membuka file yang dipetakan memori yang ada dengan menggunakan OpenExisting metode yang mengambil MemoryMappedFileRights sebagai parameter.

Selain itu, Anda dapat menyertakan MemoryMappedFileSecurity objek yang berisi aturan akses yang telah ditentukan sebelumnya.

Untuk menerapkan aturan akses baru atau yang diubah ke file yang dipetakan memori, gunakan metode .SetAccessControl Untuk mengambil aturan akses atau audit dari file yang ada, gunakan metode .GetAccessControl

Contoh

File Memory-Mapped yang Dipertahankan

Metode CreateFromFile membuat file yang dipetakan ke memori dari file yang sudah ada di disk.

Contoh berikut membuat tampilan yang dipetakan memori dari bagian dari file yang sangat besar dan memanipulasi sebagiannya.

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

Contoh berikut membuka file peta memori yang sama untuk proses lain.

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

File Memory-Mapped yang Tidak Tersimpan Permanen

Metode CreateNew dan CreateOrOpen membuat file yang dipetakan memori yang tidak dipetakan ke file yang ada pada disk.

Contoh berikut terdiri dari tiga proses terpisah (aplikasi konsol) yang menulis nilai Boolean ke file yang dipetakan memori. Urutan tindakan berikut terjadi:

  1. Process A membuat file yang dipetakan dalam memori dan menulis nilai ke dalamnya.

  2. Process B membuka file yang dipetakan memori dan menulis nilai ke file tersebut.

  3. Process C membuka file yang dipetakan memori dan menulis nilai ke file tersebut.

  4. Process A membaca dan menampilkan nilai dari file yang dipetakan memori.

  5. Setelah Process A selesai dengan file dengan pemetaan memori, file tersebut segera diambil kembali oleh pengumpulan sampah.

Untuk menjalankan contoh ini, lakukan hal berikut:

  1. Kompilasi aplikasi dan buka tiga jendela Prompt Perintah.

  2. Pada jendela Prompt Perintah pertama, jalankan Process A.

  3. Di jendela Prompt Perintah kedua, jalankan Process B.

  4. Kembali ke Process A dan tekan ENTER.

  5. Pada jendela Prompt Perintah ketiga, jalankan Process C.

  6. Kembali ke Process A dan tekan ENTER.

Outputnya Process A adalah sebagai berikut:

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  

Proses 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: {reader.ReadBoolean()}");
                Console.WriteLine($"Process B says: {reader.ReadBoolean()}");
                Console.WriteLine($"Process C says: {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

Proses 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

Proses 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

Lihat juga