次の方法で共有


メモリ マップト ファイル

メモリ マップト ファイルには、仮想メモリ内のファイルの内容が含まれます。 ファイルとメモリ領域の間のこのマッピングにより、複数のプロセスを含むアプリケーションは、メモリへの直接読み取りと書き込みを行ってファイルを変更できます。 マネージド コードを使用すると、「Memory-Mapped ファイルの管理」の説明に従って、ネイティブ Windows 関数がメモリ マップファイルにアクセスするのと同じ方法で、メモリ マップ ト ファイルにアクセスできます。

メモリ マップト ファイルには、次の 2 種類があります。

  • 永続化メモリ マップト ファイル

    永続化されたファイルは、ディスク上のソース ファイルに関連付けられているメモリ マップト ファイルです。 最後のプロセスでファイルの操作が完了すると、データはディスク上のソース ファイルに保存されます。 これらのメモリ マップファイルは、非常に大きなソース ファイルの操作に適しています。

  • 非永続化メモリ マップト ファイル

    非永続化ファイルは、ディスク上のファイルに関連付けられていないメモリ マップファイルです。 最後のプロセスがファイルの操作を完了すると、データは失われ、ファイルはガベージ コレクションによって再利用されます。 これらのファイルは、プロセス間通信 (IPC) 用の共有メモリを作成するのに適しています。

プロセス、ビュー、およびメモリの管理

メモリ マップト ファイルは、複数のプロセス間で共有できます。 プロセスは、ファイルを作成したプロセスによって割り当てられた共通名を使用して、同じメモリ マップ ファイルにマップできます。

メモリ マップト ファイルを操作するには、メモリ マップファイル全体またはその一部のビューを作成する必要があります。 メモリ マップファイルの同じ部分に対して複数のビューを作成して、同時実行メモリを作成することもできます。 2 つのビューを同時に維持するには、同じメモリ マップト ファイルから作成する必要があります。

ファイルがメモリ マッピングに使用できるアプリケーションの論理メモリ領域のサイズ (32 ビット コンピューターでは 2 GB) より大きい場合は、複数のビューが必要になる場合もあります。

ビューには、ストリーム アクセス ビューとランダム アクセス ビューの 2 種類があります。 ファイルへの順次アクセスにはストリーム アクセス ビューを使用します。これは、非永続化ファイルと IPC に推奨されます。 永続化されたファイルを操作する場合は、ランダム アクセス ビューを使用することをお勧めします。

メモリ マップファイルはオペレーティング システムのメモリ マネージャーを介してアクセスされるため、ファイルは自動的に複数のページにパーティション分割され、必要に応じてアクセスされます。 メモリ管理を自分で処理する必要はありません。

次の図は、複数のプロセスが同一のメモリ マップ ファイルに対して複数の重複ビューを同時に持つ方法を示しています。

次の画像では、メモリ マップト ファイルへの複数の重なるビューを確認できます。

メモリ マップト ファイルへのビューを示すスクリーンショット。

Memory-Mapped ファイルを使用したプログラミング

次の表に、メモリ マップト ファイル オブジェクトとそのメンバーを使用するためのガイドを示します。

課題 使用するメソッドまたはプロパティ
ディスク上のファイルから、永続化されたメモリ マップト ファイルを表す MemoryMappedFile オブジェクトを取得します。 MemoryMappedFile.CreateFromFile メソッド
非永続化メモリ マップト ファイル (ディスク上のファイルに関連付けられていない) を表す MemoryMappedFile オブジェクトを取得します。 MemoryMappedFile.CreateNew メソッド

-又は-

MemoryMappedFile.CreateOrOpen メソッド
既存の (永続化または非永続化) メモリ マップト ファイルの MemoryMappedFile オブジェクトを取得する。 MemoryMappedFile.OpenExisting メソッド
メモリ マップト ファイルに連続してアクセスされるビューの UnmanagedMemoryStream オブジェクトを取得します。 MemoryMappedFile.CreateViewStream メソッド
メモリ マップト ファイルへのランダム アクセス ビューの UnmanagedMemoryAccessor オブジェクトを取得します。 MemoryMappedFile.CreateViewAccessor メソッド
アンマネージ コードで使用する SafeMemoryMappedViewHandle オブジェクトを取得します。 MemoryMappedFile.SafeMemoryMappedFileHandle プロパティ。

-又は-

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle プロパティ。

-又は-

MemoryMappedViewStream.SafeMemoryMappedViewHandle プロパティ。
ビューが作成されるまでメモリの割り当てを遅らせる (非永続化ファイルのみ)。

(現在のシステム ページ サイズを確認するには、 Environment.SystemPageSize プロパティを使用します)。
CreateNew値を持つ MemoryMappedFileOptions.DelayAllocatePages メソッド。

-又は-

CreateOrOpen MemoryMappedFileOptions列挙体をパラメーターとして持つメソッド。

安全

メモリ マップト ファイルを作成するときにアクセス権を適用するには、 MemoryMappedFileAccess 列挙体をパラメーターとして受け取る次のメソッドを使用します。

OpenExistingをパラメーターとして受け取るMemoryMappedFileRights メソッドを使用して、既存のメモリ マップト ファイルを開くアクセス権を指定できます。

さらに、定義済みのアクセス規則を含む MemoryMappedFileSecurity オブジェクトを含めることができます。

メモリ マップト ファイルに新しいアクセス規則または変更されたアクセス規則を適用するには、 SetAccessControl メソッドを使用します。 既存のファイルからアクセス規則または監査規則を取得するには、 GetAccessControl メソッドを使用します。

例示

永続化メモリ マップト ファイル

CreateFromFileメソッドは、ディスク上の既存のファイルからメモリ マップト ファイルを作成します。

次の例では、非常に大きなファイルの一部のメモリ マップビューを作成し、その一部を操作します。

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

次の例では、別のプロセスに対して同じメモリ マップト ファイルを開きます。

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

非永続化メモリ マップト ファイル

CreateNewメソッドと CreateOrOpen メソッドは、ディスク上の既存のファイルにマップされていないメモリ マップト ファイルを作成します。

次の例は、メモリ マップト ファイルにブール値を書き込む 3 つの個別のプロセス (コンソール アプリケーション) で構成されています。 次の一連のアクションが発生します。

  1. Process A では、メモリ マップト ファイルが作成され、値が書き込まれます。

  2. Process B は、メモリ マップト ファイルを開き、値を書き込みます。

  3. Process C は、メモリ マップト ファイルを開き、値を書き込みます。

  4. Process A は、メモリ マップト ファイルから値を読み取って表示します。

  5. Process A がメモリ マップト ファイルの処理を終了すると、ガベージ コレクションによってファイルが直ちにクリアされます。

この例を実行するには、次の操作を行います。

  1. アプリケーションをコンパイルし、3 つのコマンド プロンプト ウィンドウを開きます。

  2. 最初のコマンド プロンプト ウィンドウで、 Process Aを実行します。

  3. 2 番目のコマンド プロンプト ウィンドウで、 Process Bを実行します。

  4. Process Aに戻り、Enter キーを押します。

  5. 3 番目のコマンド プロンプト ウィンドウで、 Process C実行します。

  6. Process Aに戻り、Enter キーを押します。

Process Aの出力は次のとおりです。

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  

プロセス 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

プロセス 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

プロセス 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

こちらも参照ください