Arbeiten mit Speicherzuordnungsdateien in .Net

Der Dateizugriff ist ein ressourcenintensiver Vorgang. Der Zugriff auf eine Datei von der Festplatte für eine Anwendung ist zeitaufwändig, und der Zugriff auf Daten aus dem Primärspeicher ist immer schneller. Was ist, wenn sich die Datenträgerdateien, von denen Ihre Anwendung lesen oder schreiben muss, im Speicher befinden? Genau hier setzt das Konzept der Speicherzuordnungsdateien an. In diesem Artikel werden wir untersuchen, wie wir mit Speicherzuordnungsdateien in .Net arbeiten können.

Einführung in Speicherzuordnungsdateien

Eine Speicherzuordnungsdatei ist ein Kernelobjekt, mit dem eine Datei auf Ihrer Festplatte einer Region im Primärspeicher zugeordnet wird. Speicherzugeordnete Dateien können im Vergleich zum direkten Festplattenzugriff erhebliche Leistungsgewinne erzielen, wenn mit großen Datenmengen oder großen Bildern gearbeitet wird. Speicherzuordnungsdateien waren Teil der Win32-API, aber bis vor kurzem konnten Sie nur C ++ oder PInvoke verwenden, um Code zu schreiben, der Speicherzuordnungsdateien in Ihrer Anwendung nutzt. Mit .Net Framework 4 können Sie jetzt jedoch direkt aus Ihren .Net-Anwendungen mit Speicherzuordnungsdateien arbeiten. Die Laufzeit bietet Ihnen jetzt einen verwalteten Wrapper mit allen erforderlichen Wrapper-Klassen zum Aufrufen der Win32-API. In der MSDN heißt es: "Eine Speicherzuordnungsdatei enthält den Inhalt einer Datei im virtuellen Speicher. Diese Zuordnung zwischen einer Datei und dem Speicherplatz ermöglicht eine Anwendung, die mehrere Prozesse umfasst.um die Datei durch Lesen und Schreiben direkt in den Speicher zu ändern. "

Warum benötigen Sie Speicherzuordnungsdateien?

Speicherzugeordnete Dateien sind eine gute Wahl, wenn Sie mit einer großen Datenmenge arbeiten müssen und die mit dem Marshalling und Un-Marshalling verbundenen Kosten vermeiden möchten, während Sie Daten über Prozessgrenzen hinweg gemeinsam nutzen. Speicherzugeordnete Dateien eignen sich hervorragend zum Verarbeiten einer großen Datei. Das Lesen einer großen Datei ist eine ressourcenintensive Operation. Mit Speicherzuordnungsdateien können Sie einen bestimmten Teil Ihrer Datei dem Speicher zuordnen und mit diesem Block E / A-Vorgänge ausführen, um den Zugriff zu beschleunigen.

Mit einer Speicherzuordnungsdatei können Sie einen Bereich von Speicheradressen reservieren und eine Festplattendatei als physischen Speicher für die reservierte Adresse verwenden. Mit anderen Worten, Sie können einen Speicherplatz im Speicher reservieren und dann physischen Speicher für diese Region festlegen. Auf diese Weise können Sie auf Daten auf der Festplatte zugreifen, ohne eine Datei-E / A-Operation ausführen zu müssen. Mit Speicherzuordnungsdateien können Sie auch Daten für mehrere Prozesse freigeben. Das Betriebssystem kümmert sich um die Verwaltung des Speichers für Dateien mit Speicherzuordnung - Sie müssen sich nicht darum kümmern, wie die Datei in Seiten aufgeteilt und verwaltet wird. Sie können die Sicherheit auch in Ihrer Speicherzuordnungsdatei anwenden, indem Sie beim Erstellen der Speicherzuordnungsdatei die Enumeration MemoryMappedFileAccess als Parameter verwenden. 

Persistente und nicht persistente Speicherzuordnungsdateien

Grundsätzlich gibt es zwei Arten von Speicherzuordnungsdateien. Diese sind:

Persistent : Persistent speicherabgebildete Dateien sind solche, die einer Quelldatei auf der Festplatte Ihres Systems zugeordnet sind. Wenn Sie mit diesen Arten von Dateien mit Speicherzuordnung arbeiten, bleiben die Daten auf der Festplatte erhalten, nachdem der letzte Prozess, der an der Datei arbeitet, seine Aktivität beendet hat.

Nicht persistent : Nicht persistente Speicherzuordnungsdateien sind solche, die keiner Festplattendatei zugeordnet sind. Wenn Sie mit dieser Art von Speicherzuordnungsdateien arbeiten, bleiben die Daten nicht erhalten, nachdem der letzte Prozess, der an der Datei arbeitet, seine Arbeit beendet hat. Nicht persistente Speicherzuordnungsdateien eignen sich hervorragend für die gemeinsame Nutzung von Speicher für die Kommunikation zwischen Prozessen.

Erstellen von Dateien mit persistenter Speicherzuordnung

Um eine persistente Speicherzuordnungsdatei zu erstellen, müssen Sie die CreateFromFile-Methode der MemoryMappedFile-Klasse verwenden. Die MemorymappedFile-Klasse ist im System.IO.MemoryMappedFiles-Namespace vorhanden.

Das folgende Codeausschnitt verwendet die CreateFromFile-Methode, um eine Speicherzuordnungsdatei zu erstellen. Als Nächstes wird eine speicherabgebildete Ansicht für einen Teil der Datei erstellt.

static long offset = 0x10000000; // 256 megabytes

static long length = 0x20000000; // 512 megabytes

        static void Main()

        {

            using (var memoryMappedFile = MemoryMappedFile.CreateFromFile("F:\\ImageData.png", FileMode.Open, "PartitionA"))

            {

                using (var accessor = memoryMappedFile.CreateViewAccessor(offset, length))

                {

                    //Other code

                }

            }

        } 

Das folgende Codefragment zeigt, wie Sie Daten aus einer Speicherzuordnungsdatei lesen können.

using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile("F:\\LargeData.dat"))

            {

                using (MemoryMappedViewStream memoryMappedViewStream = memoryMappedFile.CreateViewStream(0, 1204, MemoryMappedFileAccess.Read))

                {

                    var contentArray = new byte[1024];

                    memoryMappedViewStream.Read(contentArray, 0, contentArray.Length);

                    string content = Encoding.UTF8.GetString(contentArray);

                }

            }

Erstellen nicht persistenter Speicherzuordnungsdateien

Um nicht persistente Speicherzuordnungsdateien zu erstellen, dh Dateien, die keiner vorhandenen Datei auf der Festplatte zugeordnet sind, müssen Sie die Methoden CreateNew und CreateOrOpen nutzen.

Das folgende Codeausschnitt zeigt, wie eine nicht persistente Speicherzuordnungsdatei erstellt werden kann.

using(MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateNew("idg.txt", 5))

            {

                using(MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor())

                {

                var data = new[] { (byte)'I', (byte)'D', (byte)'G'};

                for (int i = 0; i < data.Length; i++)

                    memoryMappedViewAccessor.Write(i, data[i]);

                memoryMappedViewAccessor.Dispose();

                memoryMappedFile.Dispose();

                }

            }

Weitere Informationen zu Speicherzuordnungsdateien finden Sie in diesem MSDN-Artikel.