Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Un fichier mappé en mémoire contient le contenu d’un fichier en mémoire virtuelle. Ce mappage entre un fichier et un espace mémoire permet à une application, y compris plusieurs processus, de modifier le fichier en lisant et en écrivant directement dans la mémoire. Vous pouvez utiliser du code managé pour accéder aux fichiers mappés en mémoire de la même façon que les fonctions Windows natives accèdent aux fichiers mappés en mémoire, comme décrit dans Gestion des fichiers Memory-Mapped.
Il existe deux types de fichiers mappés en mémoire :
Fichiers mappés en mémoire persistante
Les fichiers persistants sont des fichiers mappés en mémoire associés à un fichier source sur un disque. Lorsque le dernier processus a terminé d’utiliser le fichier, les données sont enregistrées dans le fichier source sur le disque. Ces fichiers mappés en mémoire conviennent à l’utilisation de fichiers sources extrêmement volumineux.
Fichiers mappés en mémoire non persistants
Les fichiers non persistants sont des fichiers mappés en mémoire qui ne sont pas associés à un fichier sur un disque. Lorsque le dernier processus a terminé d’utiliser le fichier, les données sont perdues et le fichier est récupéré par le ramasse-miettes. Ces fichiers sont adaptés à la création d’une mémoire partagée pour les communications interprocesseur (IPC).
Processus, vues et gestion de la mémoire
Les fichiers mappés en mémoire peuvent être partagés entre plusieurs processus. Les processus peuvent être mappés au même fichier mappé en mémoire à l’aide d’un nom commun affecté par le processus qui a créé le fichier.
Pour utiliser un fichier mappé en mémoire, vous devez créer une vue de l’ensemble du fichier mappé en mémoire ou d’une partie de celui-ci. Vous pouvez également créer plusieurs vues dans la même partie du fichier mappé en mémoire, créant ainsi une mémoire simultanée. Pour que deux vues restent simultanées, elles doivent être créées à partir du même fichier mappé en mémoire.
Plusieurs vues peuvent également être nécessaires si le fichier est supérieur à la taille de l’espace mémoire logique de l’application disponible pour le mappage de mémoire (2 Go sur un ordinateur 32 bits).
Il existe deux types de vues : la vue d’accès en flux et la vue d’accès aléatoire. Utilisez des vues d’accès en flux pour l’accès séquentiel à un fichier ; ceci est recommandé pour les fichiers non persistants et IPC. Les vues d’accès aléatoire sont préférées pour utiliser des fichiers persistants.
Les fichiers mappés en mémoire sont accessibles via le gestionnaire de mémoire du système d’exploitation. Le fichier est donc automatiquement partitionné en plusieurs pages et accessible en fonction des besoins. Vous n’avez pas besoin de gérer vous-même la gestion de la mémoire.
L’illustration suivante montre comment plusieurs processus peuvent avoir plusieurs vues qui se chevauchent dans le même fichier mappé en mémoire en même temps.
L’image suivante montre plusieurs vues qui se chevauchent dans un fichier mappé en mémoire :
Programmation avec des fichiers Memory-Mapped
Le tableau suivant fournit un guide pour l’utilisation d’objets de fichier mappés en mémoire et de leurs membres.
Tâche | Méthodes ou propriétés à utiliser |
---|---|
Pour obtenir un MemoryMappedFile objet qui représente un fichier mappé en mémoire persistante à partir d’un fichier sur disque. | MéthodeMemoryMappedFile.CreateFromFile . |
Pour obtenir un MemoryMappedFile objet qui représente un fichier mappé en mémoire non persistant (non associé à un fichier sur le disque). | MéthodeMemoryMappedFile.CreateNew . ou MéthodeMemoryMappedFile.CreateOrOpen . |
Pour obtenir un objet MemoryMappedFile d’un fichier mappé en mémoire existant (persistant ou non persistant). | MéthodeMemoryMappedFile.OpenExisting . |
Pour obtenir un objet UnmanagedMemoryStream pour une vue à accès séquentiel dans le fichier mappé en mémoire. | MéthodeMemoryMappedFile.CreateViewStream . |
Pour obtenir un UnmanagedMemoryAccessor objet pour une vue d’accès aléatoire à un fichier mappé en mémoire. | MéthodeMemoryMappedFile.CreateViewAccessor . |
Pour obtenir un SafeMemoryMappedViewHandle objet à utiliser avec du code non managé. | Propriété MemoryMappedFile.SafeMemoryMappedFileHandle. ou Propriété MemoryMappedViewAccessor.SafeMemoryMappedViewHandle. ou Propriété MemoryMappedViewStream.SafeMemoryMappedViewHandle. |
Pour retarder l’allocation de mémoire jusqu’à ce qu’une vue soit créée (fichiers non persistants uniquement). (Pour déterminer la taille actuelle de la page système, utilisez la Environment.SystemPageSize propriété.) |
Méthode CreateNew avec la valeur MemoryMappedFileOptions.DelayAllocatePages. ou CreateOrOpen méthodes qui ont une MemoryMappedFileOptions énumération comme paramètre. |
Sécurité
Vous pouvez appliquer des droits d’accès lorsque vous créez un fichier mappé en mémoire à l’aide des méthodes suivantes qui prennent une MemoryMappedFileAccess énumération en tant que paramètre :
Vous pouvez spécifier des droits d’accès pour ouvrir un fichier mappé en mémoire existant en utilisant les méthodes OpenExisting qui acceptent un paramètre MemoryMappedFileRights.
En outre, vous pouvez inclure un objet qui contient des règles d’accès MemoryMappedFileSecurity prédéfinies.
Pour appliquer des règles d’accès nouvelles ou modifiées à un fichier mappé en mémoire, utilisez la SetAccessControl méthode. Pour récupérer des règles d’accès ou d’audit à partir d’un fichier existant, utilisez la GetAccessControl méthode.
Exemples
Fichiers mappés en mémoire persistants
Les CreateFromFile méthodes créent un fichier mappé en mémoire à partir d’un fichier existant sur le disque.
L’exemple suivant crée une vue mappée en mémoire d’une partie d’un fichier extrêmement volumineux et manipule une partie de celui-ci.
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
L’exemple suivant ouvre le même fichier mappé en mémoire pour un autre processus.
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
Fichiers mappés en mémoire non persistants
Les méthodes CreateNew et CreateOrOpen créent un fichier mappé en mémoire qui n’est pas associé à un fichier existant sur le disque.
L’exemple suivant se compose de trois processus distincts (applications console) qui écrivent des valeurs booléennes dans un fichier mappé en mémoire. La séquence d’actions suivante se produit :
Process A
crée le fichier mappé en mémoire et écrit une valeur dans celui-ci.Process B
ouvre le fichier mappé en mémoire et écrit une valeur dans celui-ci.Process C
ouvre le fichier mappé en mémoire et écrit une valeur dans celui-ci.Process A
lit et affiche les valeurs du fichier mappé en mémoire.Une fois que
Process A
a terminé avec le fichier mappé en mémoire, celui-ci est immédiatement récupéré par la collecte des ordures.
Pour exécuter cet exemple, procédez comme suit :
Compilez les applications et ouvrez trois fenêtres d'invite de commande.
Dans la première fenêtre d’invite de commande, exécutez
Process A
.Dans la deuxième fenêtre d’invite de commandes, exécutez
Process B
.Revenez à
Process A
et appuyez sur Entrée.Dans la troisième fenêtre d’invite de commandes, exécutez
Process C
.Revenez à
Process A
et appuyez sur Entrée.
La sortie de Process A
est la suivante :
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
Processus 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
Processus 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
Processus 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