Сопоставленные в памяти файлы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, вы можете использовать управляемый код для доступа к отображенным в память файлам тем же способом, что и собственные функции Windows. Описание этого механизма можно найти на странице Managing Memory-Mapped File (Управление отображенными в память файлами).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.

Есть два типа отображенных в память файлов: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. Чтобы два представления оставались согласованными, их нужно создавать из одного отображенного в память файла.For two views to remain concurrent, they have to be created from the same memory-mapped file.

Несколько представлений потребуются еще и в том случае, если размер файла превышает размер пространства логической памяти, доступной приложению для отображения в память (например, 2 ГБ на 32-разрядном компьютере).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).

Есть два типа представлений: представление потокового доступа и представление произвольного доступа.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.

Приведенный ниже пример состоит из трех отдельных процессов (консольных приложений), при которых логические значения записываются в отображенный в память файл.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. Скомпилируйте приложение и откройте три окна командной строки.Compile the applications and open three Command Prompt windows.

  2. В первом окне командной строки выполните команду Process A.In the first Command Prompt window, run Process A.

  3. Во втором окне командной строки выполните команду Process B.In the second Command Prompt window, run Process B.

  4. Вернитесь к Process A и нажмите клавишу ВВОД.Return to Process A and press ENTER.

  5. В третьем окне командной строки выполните команду Process C.In the third Command Prompt window, run Process C.

  6. Вернитесь к Process A и нажмите клавишу ВВОД.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  

Process 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

Process 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

Process 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