メモリ マップト ファイルMemory-Mapped Files

メモリ マップト ファイルには、仮想メモリ内のファイルの内容が含まれています。A memory-mapped file contains the contents of a file in virtual memory. ファイルとメモリ空間の間のこのマッピングによって、複数のプロセスを含むアプリケーションは、メモリを直接読み書きすることでファイルを変更できます。This mapping between a file and memory space enables an application, including multiple processes, to modify the file by reading and writing directly to the memory. .NET Framework 4 以降では、「Managing Memory-Mapped Files」 (メモリ マップ ファイルの管理) で説明されているように、マネージド コードを使用して、ネイティブ Windows 関数がメモリ マップ ファイルにアクセスする場合と同じ方法でメモリ マップ ファイルにアクセスできます。Starting with the .NET Framework 4, you can use managed code to access memory-mapped files in the same way that native Windows functions access memory-mapped files, as described in Managing Memory-Mapped Files.

メモリ マップト ファイルには次の 2 種類があります。There are two types of memory-mapped files:

  • 永続化メモリ マップト ファイルPersisted memory-mapped files

    永続化ファイルは、ディスク上のソース ファイルに関連付けられているメモリ マップト ファイルです。Persisted files are memory-mapped files that are associated with a source file on a disk. 最後のプロセスがファイルの操作を終了すると、データがディスク上のソース ファイルに保存されます。When the last process has finished working with the file, the data is saved to the source file on the disk. これらのメモリ マップト ファイルは、きわめて大きなソース ファイルの操作に適しています。These memory-mapped files are suitable for working with extremely large source files.

  • 非永続化メモリ マップト ファイルNon-persisted memory-mapped files

    非永続化ファイルは、ディスク上のファイルに関連付けられていないメモリ マップト ファイルです。Non-persisted files are memory-mapped files that are not associated with a file on a disk. 最後のプロセスがファイルの操作を終了すると、データが失われ、ガベージ コレクションによってファイルが解放されます。When the last process has finished working with the file, the data is lost and the file is reclaimed by garbage collection. これらのファイルは、プロセス間通信 (IPC) 用の共有メモリの作成に適しています。These files are suitable for creating shared memory for inter-process communications (IPC).

プロセス、ビュー、およびメモリ管理Processes, Views, and Managing Memory

メモリ マップト ファイルは、複数のプロセス間で共有できます。Memory-mapped files can be shared across multiple processes. ファイルを作成したプロセスによって割り当てられている共通名を使用して、複数のプロセスを同じメモリ マップト ファイルにマップできます。Processes can map to the same memory-mapped file by using a common name that is assigned by the process that created the file.

メモリ マップト ファイルを操作するには、メモリ マップト ファイル全体またはその一部のビューを作成する必要があります。To work with a memory-mapped file, you must create a view of the entire memory-mapped file or a part of it. また、メモリ マップト ファイルの同じ部分に対するマルチ ビューを作成し、それによって同時実行メモリを作成することもできます。You can also create multiple views to the same part of the memory-mapped file, thereby creating concurrent memory. 2 つのビューが同時実行されるには、それらのビューを同じメモリ マップト ファイルから作成する必要があります。For two views to remain concurrent, they have to be created from the same memory-mapped file.

ファイルがメモリ マッピングで使用できるアプリケーションの論理メモリ空間のサイズ (32 ビット コンピューターでは 2 GB) よりも大きい場合にも、マルチ ビューが必要になる可能性があります。Multiple views may also be necessary if the file is greater than the size of the application’s logical memory space available for memory mapping (2 GB on a 32-bit computer).

ビューには、ストリーム アクセス ビューとランダム アクセス ビューの 2 種類があります。There are two types of views: stream access view and random access view. ファイルへの順次アクセスにはストリーム アクセス ビューを使用します。これは、非永続化ファイルと IPC に推奨されます。Use stream access views for sequential access to a file; this is recommended for non-persisted files and IPC. ランダム アクセス ビューは、永続化ファイルの操作に適しています。Random access views are preferred for working with persisted files.

メモリ マップト ファイルへは、オペレーティング システムのメモリ マネージャーを通じてアクセスするため、ファイルは複数のページに自動的に分割され、必要に応じてアクセスされます。Memory-mapped files are accessed through the operating system’s memory manager, so the file is automatically partitioned into a number of pages and accessed as needed. メモリ管理を自分で行う必要はありません。You do not have to handle the memory management yourself.

次の図に、複数のプロセスがどのように同じメモリ マップト ファイルへの複数の重なるビューを同時に持つことができるかを示します。The following illustration shows how multiple processes can have multiple and overlapping views to the same memory-mapped file at the same time.

次の画像では、メモリ マップト ファイルへの複数の重なるビューを確認できます。The following image shows multiple and overlapped views to a memory-mapped file:

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

メモリ マップト ファイルのプログラミングProgramming with Memory-Mapped Files

メモリ マップト ファイル オブジェクトとそのメンバーを使用するための手引きを次の表に示します。The following table provides a guide for using memory-mapped file objects and their members.

タスクTask 使用するメソッドまたはプロパティMethods or properties to use
ディスク上のファイルからの永続化メモリ マップト ファイルを表す MemoryMappedFile オブジェクトを取得する。To obtain a MemoryMappedFile object that represents a persisted memory-mapped file from a file on disk. MemoryMappedFile.CreateFromFile メソッドMemoryMappedFile.CreateFromFile method.
(ディスク上のファイルに関連付けられていない) 非永続化メモリ マップト ファイルを表す MemoryMappedFile オブジェクトを取得する。To obtain a MemoryMappedFile object that represents a non-persisted memory-mapped file (not associated with a file on disk). MemoryMappedFile.CreateNew メソッドMemoryMappedFile.CreateNew method.

または- or -

MemoryMappedFile.CreateOrOpen メソッドMemoryMappedFile.CreateOrOpen method.
既存の (永続化または非永続化) メモリ マップト ファイルの MemoryMappedFile オブジェクトを取得する。To obtain a MemoryMappedFile object of an existing memory-mapped file (either persisted or non-persisted). MemoryMappedFile.OpenExisting メソッドMemoryMappedFile.OpenExisting method.
メモリ マップト ファイルへの順次アクセス ビューを表す UnmanagedMemoryStream オブジェクトを取得する。To obtain a UnmanagedMemoryStream object for a sequentially accessed view to the memory-mapped file. MemoryMappedFile.CreateViewStream メソッドMemoryMappedFile.CreateViewStream method.
メモリ マップト ファイルへのランダム アクセス ビューを表す UnmanagedMemoryAccessor を取得する。To obtain a UnmanagedMemoryAccessor object for a random access view to a memory-mapped fie. MemoryMappedFile.CreateViewAccessor メソッドMemoryMappedFile.CreateViewAccessor method.
アンマネージ コードで使用するために SafeMemoryMappedViewHandle オブジェクトを取得する。To obtain a SafeMemoryMappedViewHandle object to use with unmanaged code. MemoryMappedFile.SafeMemoryMappedFileHandle プロパティ。MemoryMappedFile.SafeMemoryMappedFileHandle property.

または- or -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle プロパティ。MemoryMappedViewAccessor.SafeMemoryMappedViewHandle property.

または- or -

MemoryMappedViewStream.SafeMemoryMappedViewHandle プロパティ。MemoryMappedViewStream.SafeMemoryMappedViewHandle property.
ビューが作成されるまで、メモリ割り当てを延期する (非永続化ファイルのみ)。To delay allocating memory until a view is created (non-persisted files only).

(現在のシステム ページ サイズを確認するには、Environment.SystemPageSize プロパティを使用します)。(To determine the current system page size, use the Environment.SystemPageSize property.)
CreateNew 値を持つ MemoryMappedFileOptions.DelayAllocatePages メソッドCreateNew method with the MemoryMappedFileOptions.DelayAllocatePages value.

または- or -

CreateOrOpen 列挙体をパラメーターとして持つ MemoryMappedFileOptions メソッド。CreateOrOpen methods that have a MemoryMappedFileOptions enumeration as a parameter.

セキュリティSecurity

MemoryMappedFileAccess 列挙体をパラメーターとして受け取る次のメソッドを使用して、メモリ マップト ファイルの作成時にアクセス権を適用できます。You can apply access rights when you create a memory-mapped file, by using the following methods that take a MemoryMappedFileAccess enumeration as a parameter:

OpenExisting をパラメーターとして受け取る MemoryMappedFileRights メソッドを使用して、既存のメモリ マップト ファイルを開く操作に対するアクセス権を指定できます。You can specify access rights for opening an existing memory-mapped file by using the OpenExisting methods that take an MemoryMappedFileRights as a parameter.

また、定義済みのアクセス規則が格納されている MemoryMappedFileSecurity オブジェクトを含めることもできます。In addition, you can include a MemoryMappedFileSecurity object that contains predefined access rules.

メモリ マップト ファイルに新規または変更済みのアクセス規則を適用するには、SetAccessControl メソッドを使用します。To apply new or changed access rules to a memory-mapped file, use the SetAccessControl method. 既存のファイルからアクセス規則または監査規則を取得するには、GetAccessControl メソッドを使用します。To retrieve access or audit rules from an existing file, use the GetAccessControl method.

使用例Examples

永続化メモリ マップト ファイルPersisted Memory-Mapped Files

CreateFromFile メソッドは、ディスク上の既存のファイルからメモリ マップト ファイルを作成します。The CreateFromFile methods create a memory-mapped file from an existing file on disk.

次の例では、きわめて大きなファイルの一部のメモリ マップト ビューを作成し、その一部分を操作します。The following example creates a memory-mapped view of a part of an extremely large file and manipulates a portion of it.

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

別のプロセスに対して同じメモリ マップト ファイルを開く例を、次に示します。The following example opens the same memory-mapped file for another 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

非永続化メモリ マップト ファイルNon-Persisted Memory-Mapped Files

CreateNew メソッドおよび CreateOrOpen メソッドは、ディスク上の既存のファイルに対応付けられないメモリ マップト ファイルを作成します。The CreateNew and CreateOrOpen methods create a memory-mapped file that is not mapped to an existing file on disk.

次の例は、メモリ マップト ファイルにブール値を書き込む、3 つの独立したプロセス (コンソール アプリケーション) で構成されます。The following example consists of three separate processes (console applications) that write Boolean values to a memory-mapped file. 次の順序で処理が実行されます。The following sequence of actions occur:

  1. Process A がメモリ マップト ファイルを作成し、値を書き込みます。Process A creates the memory-mapped file and writes a value to it.

  2. Process B がメモリ マップト ファイルを開き、値を書き込みます。Process B opens the memory-mapped file and writes a value to it.

  3. Process C がメモリ マップト ファイルを開き、値を書き込みます。Process C opens the memory-mapped file and writes a value to it.

  4. Process A がメモリ マップト ファイルの値を読み込み、表示します。Process A reads and displays the values from the memory-mapped file.

  5. Process A がメモリ マップト ファイルの処理を終了すると、ガベージ コレクションによってファイルが直ちにクリアされます。After Process A is finished with the memory-mapped file, the file is immediately reclaimed by garbage collection.

この例を実行するには、次の手順に従います。To run this example, do the following:

  1. アプリケーションをコンパイルし、3 つのコマンド プロンプト ウィンドウを開きます。Compile the applications and open three Command Prompt windows.

  2. 最初のコマンド プロンプト ウィンドウで、Process A を実行します。In the first Command Prompt window, run Process A.

  3. 2 つ目のコマンド プロンプト ウィンドウで、Process B を実行します。In the second Command Prompt window, run Process B.

  4. Process A に戻り、Enter キーを押します。Return to Process A and press ENTER.

  5. 3 つ目のコマンド プロンプト ウィンドウで、Process C を実行します。In the third Command Prompt window, run Process C.

  6. Process A に戻り、Enter キーを押します。Return to Process A and press ENTER.

Process A の出力は次のとおりです。The output of Process A is as follows:

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  

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

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

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

関連項目See also