Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Сопоставленный с памятью файл содержит содержимое файла в виртуальной памяти. Это сопоставление между файлом и пространством памяти позволяет приложению, включая несколько процессов, изменять файл путем чтения и записи непосредственно в память. Управляемый код можно использовать для доступа к файлам, сопоставленным с памятью, тем же способом, что и собственные функции Windows, как описано в разделе "Управление файлами Memory-Mapped".
Существует два типа сопоставленных с памятью файлов:
Постоянные файлы с отображением в память
Персистентные файлы — это файлы с отображением в памяти, связанные с исходным файлом на диске. Когда последний процесс завершит работу с файлом, данные сохраняются в исходном файле на диске. Эти файлы, сопоставленные с памятью, подходят для работы с очень большими исходными файлами.
Файлы, которые не сохраняются в постоянной памяти и сопоставляются с памятью
Файлы, не сохраняемые на диск, — это отображаемые в памяти файлы, которые не связаны с файлом на диске. Когда последний процесс завершит работу с файлом, данные теряются, а файл удаляется сборкой мусора. Эти файлы подходят для создания общей памяти для взаимодействия между процессами (IPC).
Процессы, представления и управление памятью
Файлы, сопоставленные с памятью, можно разделять между несколькими процессами. Процессы могут сопоставляться с тем же файлом, отображаемым в памяти, с помощью общего имени, присвоенного процессом, который создал файл.
Чтобы работать с файлом, сопоставленным с памятью, необходимо создать представление всего сопоставленного с памятью файла или его части. Вы также можете создать несколько представлений к одной и той же части сопоставленного с памятью файла, тем самым создавая память с параллельным доступом. Чтобы два представления оставались одновременными, их необходимо создать из одного файла с отображением в память.
Кроме того, может потребоваться несколько представлений, если размер файла превышает размер логического пространства памяти приложения, доступного для сопоставления памяти (2 ГБ на 32-разрядном компьютере).
Существует два типа представлений: представление потокового доступа и представление случайного доступа. Используйте представления потокового доступа для последовательного доступа к файлу; это рекомендуется для неперсистентных файлов и 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 метод.
Примеры
Сохраненные файлы Memory-Mapped
Методы 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
Не сохраняемые файлы Memory-Mapped
Методы CreateNew и CreateOrOpen создают файл с отображением в память, который не связан с существующим файлом на диске.
Следующий пример состоит из трех отдельных процессов (консольных приложений), которые записывают Булевы значения в сопоставленный с памятью файл. Происходит следующая последовательность действий:
Process A
создает сопоставленный с памятью файл и записывает в него значение.Process B
открывает сопоставленный с памятью файл и записывает в него значение.Process C
открывает сопоставленный с памятью файл и записывает в него значение.Process A
считывает и отображает значения из сопоставленного с памятью файла.Как только
Process A
заканчивает работу с файлом, сопоставленным с памятью, файл немедленно восстанавливается сборкой мусора.
Чтобы выполнить этот пример, сделайте следующее:
Скомпилируйте приложения и откройте три окна командной строки.
В первом окне командной строки выполните команду
Process A
.Во втором окне командной строки выполните команду
Process B
.Вернитесь к
Process A
и нажмите клавишу ВВОД.В третьем окне командной строки выполните команду
Process C
.Вернитесь к
Process A
и нажмите клавишу ВВОД.
Выходные данные 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