메모리 매핑된 파일에는 가상 메모리에 있는 파일의 내용이 포함됩니다. 파일과 메모리 공간 간의 이 매핑을 사용하면 여러 프로세스를 포함한 애플리케이션이 메모리를 직접 읽고 쓰면서 파일을 수정할 수 있습니다. 관리 코드를 사용하여 Memory-Mapped 파일 관리에 설명된 대로 네이티브 Windows 함수가 메모리 매핑된 파일에 액세스하는 것과 동일한 방식으로 메모리 매핑 된 파일에 액세스할 수 있습니다.
다음과 같은 두 가지 유형의 메모리 매핑 파일이 있습니다.
영속적 메모리 매핑 파일
지속형 파일은 디스크의 원본 파일과 연결된 메모리 매핑 파일입니다. 마지막 프로세스가 파일 작업을 마치면 데이터가 디스크의 원본 파일에 저장됩니다. 이러한 메모리 매핑 파일은 매우 큰 소스 파일 작업에 적합합니다.
비지속 메모리 매핑 파일
비지속형 파일은 디스크의 파일과 연결되지 않은 메모리 매핑 파일입니다. 마지막 프로세스가 파일 작업을 마치면 데이터가 손실되고 가비지 수집에 의해 파일이 회수됩니다. 이러한 파일은 IPC(프로세스 간 통신)를 위한 공유 메모리를 만드는 데 적합합니다.
프로세스, 뷰 및 메모리 관리
메모리 매핑된 파일은 여러 프로세스에서 공유할 수 있습니다. 프로세스는 파일을 만든 프로세스에서 할당한 일반 이름을 사용하여 동일한 메모리 매핑 파일에 매핑할 수 있습니다.
메모리 매핑된 파일을 사용하려면 전체 메모리 매핑 파일 또는 해당 파일의 일부 보기를 만들어야 합니다. 메모리 매핑된 파일의 동일한 부분에 여러 보기를 만들어 동시 메모리를 만들 수도 있습니다. 두 뷰가 동시에 유지되려면 동일한 메모리 매핑 파일에서 만들어야 합니다.
파일이 메모리 매핑에 사용할 수 있는 애플리케이션의 논리 메모리 공간 크기보다 큰 경우에도 여러 보기가 필요할 수 있습니다(32비트 컴퓨터의 경우 2GB).
스트림 액세스 뷰와 임의 액세스 보기의 두 가지 보기 유형이 있습니다. 파일에 대한 순차적 액세스를 위해 스트림 액세스 뷰를 사용합니다. 이는 비지속형 파일 및 IPC에 권장됩니다. 임의 액세스 보기는 지속형 파일 작업에 선호됩니다.
메모리 매핑된 파일은 운영 체제의 메모리 관리자를 통해 액세스되므로 파일이 자동으로 여러 페이지로 분할되고 필요에 따라 액세스됩니다. 메모리 관리를 직접 처리할 필요가 없습니다.
다음 그림에서는 여러 프로세스에서 동일한 메모리 매핑된 파일에 동시에 여러 뷰와 겹치는 보기를 가질 수 있는 방법을 보여 줍니다.
다음 이미지는 메모리 매핑된 파일에 대한 여러 겹의 중첩된 보기를 보여줍니다.
Memory-Mapped 파일을 사용한 프로그래밍
다음 표에서는 메모리 매핑된 파일 개체와 해당 멤버를 사용하기 위한 가이드를 제공합니다.
안전
열거형을 매개변수로 사용하는 다음 메서드를 사용하여 메모리 매핑 파일을 생성할 때 MemoryMappedFileAccess 액세스 권한을 적용할 수 있습니다.
매개 변수로 사용하는 MemoryMappedFileRights 메서드를 사용하여 OpenExisting 기존 메모리 매핑 파일을 열기 위한 액세스 권한을 지정할 수 있습니다.
또한 미리 정의된 액세스 규칙을 포함하는 개체를 포함 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
으로 돌아가서 Enter 키를 누르세요.세 번째 명령 프롬프트 창에서 을 실행합니다
Process C
.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
참고하십시오
.NET