Bagikan melalui


File yang dipetakan memori

File yang dipetakan memori berisi konten 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 cara fungsi Windows asli mengakses file yang dipetakan memori, seperti yang dijelaskan dalam Mengelola File yang Dipetakan Memori.

Ada dua jenis file yang dipetakan memori:

  • File yang dipetakan memori yang bertahan

    File yang bertahan adalah file yang dipetakan memori yang terkait dengan file sumber pada 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 yang dipetakan memori yang tidak bertahan

    File yang tidak bertahan adalah file yang dipetakan memori yang tidak terkait dengan file pada disk. Ketika proses terakhir telah selesai bekerja dengan file, data hilang dan file diklaim kembali oleh pengumpulan sampah. File-file ini cocok untuk membuat memori bersama untuk komunikasi antar proses (IPC).

Proses, Tampilan, dan Pengelolaan Memori

File yang dipetakan memori dapat dibagikan di 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 sebagian darinya. Anda juga dapat membuat beberapa tampilan ke bagian yang sama dari file yang dipetakan memori, sehingga membuat memori bersamaan. Agar dua tampilan tetap bersamaan, mereka 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 stream dan tampilan akses acak. Menggunakan tampilan akses stream untuk akses berurutan ke file; ini direkomendasikan untuk file dan IPC yang tidak bertahan. Tampilan akses acak lebih disukai untuk bekerja dengan file yang bertahan.

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

Ilustrasi berikut menunjukkan bagaimana beberapa proses dapat memiliki beberapa tampilan dan tumpang tindih ke file yang dipetakan memori yang sama secara bersamaan.

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

Screenshot that shows views to a memory-mapped file.

Pemrograman dengan File yang Dipertakan Memori

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

Tugas Metode atau properti yang akan digunakan
Untuk mendapatkan objek MemoryMappedFile yang merepresentasikan file yang dipetakan memori yang bertahan dari file pada disk. MemoryMappedFile.CreateFromFile metode.
Untuk mendapatkan objek MemoryMappedFile yang merepresentasikan 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 ada (bertahan atau tidak bertahan). MemoryMappedFile.OpenExisting metode.
Untuk mendapatkan objek UnmanagedMemoryStream untuk tampilan yang diakses secara berurutan ke file yang dipetakan memori. MemoryMappedFile.CreateViewStream metode.
Untuk mendapatkan objek UnmanagedMemoryAccessor untuk tampilan akses acak ke file yang dipetakan memori. MemoryMappedFile.CreateViewAccessor metode.
Untuk mendapatkan objek SafeMemoryMappedViewHandle yang akan digunakan dengan kode tidak terkelola. properti MemoryMappedFile.SafeMemoryMappedFileHandle.

- atau -

properti MemoryMappedViewAccessor.SafeMemoryMappedViewHandle.

- atau -

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

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

- atau -

metode CreateOrOpen yang memiliki enumerasi MemoryMappedFileOptions sebagai parameter.

Keamanan

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

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

Selain itu, Anda dapat menyertakan objek MemoryMappedFileSecurity 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 yang Dipetakan Memori yang Bertahan

Metode CreateFromFile membuat file yang dipetakan memori dari file yang ada pada disk.

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

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 yang dipetakan 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 yang Dipetakan Memori yang Tidak Bertahan

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 memori dan menulis nilai untuk file tersebut.

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

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

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

  5. Setelah Process A selesai dengan file yang dipetakan memori, file segera diklaim kembali oleh pengumpulan sampah.

Untuk menjalankan contoh ini, lakukan hal berikut:

  1. Kompilasi aplikasi dan buka tiga jendela Perintah.

  2. Di jendela Perintah pertama, jalankan Process A.

  3. Di jendela Perintah kedua, jalankan Process B.

  4. Kembali ke Process A dan tekan ENTER.

  5. Di jendela Perintah ketiga, jalankan Process C.

  6. Kembali ke Process A dan tekan ENTER.

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

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