Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Um arquivo mapeado por memória contém o conteúdo de um arquivo na memória virtual. Esse mapeamento entre um arquivo e um espaço de memória permite que um aplicativo, incluindo vários processos, modifique o arquivo lendo e gravando diretamente na memória. Você pode usar o código gerenciado para acessar arquivos mapeados em memória da mesma forma que as funções nativas do Windows acessam arquivos mapeados em memória, conforme descrito no Gerenciamento de Arquivos Memory-Mapped.
Há dois tipos de arquivos mapeados em memória:
Arquivos de memória mapeada persistentes
Arquivos persistentes são arquivos mapeados em memória associados a um arquivo de origem em um disco. Quando o último processo terminar de trabalhar com o arquivo, os dados serão salvos no arquivo de origem no disco. Esses arquivos mapeados em memória são adequados para trabalhar com arquivos de origem extremamente grandes.
Arquivos não persistentes mapeados na memória
Arquivos não persistentes são arquivos mapeados em memória que não estão associados a um arquivo em um disco. Quando o último processo terminar de trabalhar com o arquivo, os dados serão perdidos e o arquivo será recuperado pela coleta de lixo. Esses arquivos são adequados para criar memória compartilhada para IPC (comunicações entre processos).
Processos, exibições e gerenciamento de memória
Arquivos mapeados em memória podem ser compartilhados em vários processos. Os processos podem ser mapeados para o mesmo arquivo mapeado em memória usando um nome comum atribuído pelo processo que criou o arquivo.
Para trabalhar com um arquivo mapeado em memória, você deve criar uma exibição de todo o arquivo mapeado em memória ou uma parte dele. Você também pode criar várias exibições para a mesma parte do arquivo mapeado pela memória, criando assim memória simultânea. Para que duas exibições permaneçam simultâneas, elas precisam ser criadas a partir do mesmo arquivo mapeado em memória.
Várias exibições também poderão ser necessárias se o arquivo for maior que o tamanho do espaço de memória lógica do aplicativo disponível para mapeamento de memória (2 GB em um computador de 32 bits).
Há dois tipos de visualizações: visualização de acesso sequencial e visualização de acesso aleatório. Use os modos de exibição de acesso por fluxo para acessos sequenciais a um arquivo. Isso é recomendado para arquivos não persistentes e IPCs. As exibições de acesso aleatório são preferenciais para trabalhar com arquivos persistentes.
Os arquivos mapeados em memória são acessados por meio do gerenciador de memória do sistema operacional, portanto, o arquivo é particionado automaticamente em várias páginas e acessado conforme necessário. Você não precisa lidar com o gerenciamento de memória por conta própria.
A ilustração a seguir mostra como vários processos podem ter várias exibições sobrepostas para o mesmo arquivo mapeado em memória ao mesmo tempo.
A imagem a seguir mostra várias exibições sobrepostas para um arquivo mapeado pela memória:
Programação com arquivos Memory-Mapped
A tabela a seguir fornece um guia para usar objetos de arquivo mapeados pela memória e seus membros.
Tarefa | Métodos ou propriedades a serem usadas |
---|---|
Para obter um objeto MemoryMappedFile de um arquivo no disco que representa um arquivo persistente mapeado na memória. | Método MemoryMappedFile.CreateFromFile. |
Para obter um MemoryMappedFile objeto que representa um arquivo mapeado por memória não persistente (não associado a um arquivo em disco). | Método MemoryMappedFile.CreateNew. - ou - Método MemoryMappedFile.CreateOrOpen. |
Para obter um objeto MemoryMappedFile de um arquivo mapeado na memória existente (persistente ou não persistente). | Método MemoryMappedFile.OpenExisting. |
Para obter um objeto UnmanagedMemoryStream para uma vista de acesso sequencial ao arquivo mapeado na memória. | Método MemoryMappedFile.CreateViewStream. |
Para obter um UnmanagedMemoryAccessor objeto para uma exibição de acesso aleatório a um arquivo mapeado pela memória. | Método MemoryMappedFile.CreateViewAccessor. |
Para obter um SafeMemoryMappedViewHandle objeto a ser usado com código não gerenciado. | Propriedade MemoryMappedFile.SafeMemoryMappedFileHandle. - ou - Propriedade MemoryMappedViewAccessor.SafeMemoryMappedViewHandle. - ou - Propriedade MemoryMappedViewStream.SafeMemoryMappedViewHandle. |
Para atrasar a alocação de memória até que uma exibição seja criada (somente arquivos não persistentes). (Para determinar o tamanho da página atual do sistema, use a Environment.SystemPageSize propriedade.) |
Método CreateNew com valor MemoryMappedFileOptions.DelayAllocatePages. - ou - CreateOrOpen métodos que têm uma MemoryMappedFileOptions enumeração como um parâmetro. |
Segurança
Você pode aplicar direitos de acesso ao criar um arquivo mapeado pela memória usando os seguintes métodos que usam uma MemoryMappedFileAccess enumeração como parâmetro:
Você pode especificar direitos de acesso para abrir um arquivo mapeado por memória existente usando os OpenExisting métodos que usam um MemoryMappedFileRights parâmetro como parâmetro.
Além disso, você pode incluir um MemoryMappedFileSecurity objeto que contém regras de acesso predefinidas.
Para aplicar regras de acesso novas ou alteradas a um arquivo mapeado pela memória, use o SetAccessControl método. Para recuperar regras de acesso ou auditoria de um arquivo existente, use o GetAccessControl método.
Exemplos
Arquivos persistentes mapeados na memória
De um arquivo existente em disco, os CreateFromFile métodos criam um arquivo mapeado em memória.
O exemplo a seguir cria uma exibição mapeada por memória de uma parte de um arquivo extremamente grande e manipula uma parte dele.
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
O exemplo a seguir abre o mesmo arquivo mapeado em memória para outro processo.
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
Arquivos não persistentes mapeados na memória
Os métodos CreateNew e CreateOrOpen criam um arquivo mapeado em memória que não é mapeado para um arquivo existente em disco.
O exemplo a seguir consiste em três processos separados (aplicativos de console) que gravam valores boolianos em um arquivo mapeado pela memória. A seguinte sequência de ações ocorre:
Process A
cria o arquivo mapeado em memória e grava um valor nele.Process B
abre o arquivo mapeado em memória e grava um valor nele.Process C
abre o arquivo mapeado em memória e grava um valor nele.Process A
lê e exibe os valores do arquivo mapeado pela memória.Após o
Process A
concluir com o arquivo mapeado na memória, o arquivo é imediatamente recuperado pela coleta de lixo.
Para executar este exemplo, faça o seguinte:
Compile os aplicativos e abra três janelas do Prompt de Comando.
Na primeira janela do Prompt de Comando, execute
Process A
.Na segunda janela do Prompt de Comando, execute
Process B
.Retorne para
Process A
e pressione ENTER.Na terceira janela do Prompt de Comando, execute
Process C
.Retorne para
Process A
e pressione ENTER.
A saída de Process A
é a seguinte:
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
Processo 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
Processo 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
Processo 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