Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Сопоставленный с памятью файл содержит содержимое файла в виртуальной памяти. Это сопоставление между файлом и пространством памяти позволяет приложению, включая несколько процессов, изменять файл путем чтения и записи непосредственно в память. Управляемый код можно использовать для доступа к файлам, сопоставленным с памятью, тем же способом, что и собственные функции 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