Zugriff auf Mega-Dateien bzw. Shared Memory in .NET

Memory-Mapped Files oder Speicherabbilddateien, wie sie so schön auf Deutsch heißen, bilden Inhalte von Dateien im virtuellen Speicher ab. Dadurch können Änderungen direkt im Speicher vorgenommen werden. Nicht nur von von der Applikation selbst, sondern auch von mehreren Prozessen. Dieser Artikel zeigt die Möglichkeiten mit .NET 4+.

Typen von Memory-mapped Files

Insgesamt stehen zwei unterschiedliche Typen zur Verfügung.

Persistierte Memory-mapped Files

Hier besteht ein Mapping zwischen einer Datei auf der Festplatte und dem Speicher. Änderungen können von mehreren Prozessen im Speicher vorgenommen werden. Wenn der letzte Prozess beendet wird, werden die Änderungen auf die Festplatte geschrieben und der Speicher wieder freigegeben. Diese Variante ist gerade für den Zugriff auf sehr große Dateien hilfreich und sinnvoll.

Nicht-persistierte Memory-mapped Files

Hier wird Speicher reserviert, der aber nicht mit einer existierenden Datei verlinkt ist. Dies wird gerne als Shared Memory für die Kommunikation zwischen mehreren Prozessen verwendet. Wenn der letzte zugreifende Prozess beendet wird, wird der Speicher wieder freigegeben.

Beispiel

Das Beispiel besteht aus zwei Konsolen-Anwendungen. Das erste erstellt einen Shared Memory und schreibt dort einen Integer-Wert hinein. Zusätzlich wird der Wert über einen Timer jede Sekunde abgegriffen und ausgegeben. Damit kann überprüft werde, ob sich der Wert verändert hat. MemoryMappedFile stellt die notwendigen Methoden zur Anlage des Speicherabbildes zur Verfügung. Via CreateViewAccessor eine View auf das gemappte File erstellt. Darauf kann im Anschluss zugegriffen werden. Via CreateViewStream kann wird ein sequentieller Zugriff ermöglicht.

class Program
{
    MemoryMappedFile mappedFile;
    Timer timer = new Timer();
    long offset = 0x00000000;
    long length = 0x00000010;

    static void Main(string[] args)
    {
        Program p = new Program();
        p.WriteData();
        p.Listen();


        Console.ReadLine();
    }        

    private void Listen()
    {
        timer.Interval = 1000;
        timer.Elapsed += Timer_Elapsed;
        timer.Enabled = true;
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        using (var accessor = mappedFile.CreateViewAccessor())
        {
            var value = accessor.ReadInt32(0);
            Console.WriteLine("Found value: " + value);
        }
    }

    private void WriteData()
    {
        mappedFile = MemoryMappedFile.CreateOrOpen("MappingTest", length, MemoryMappedFileAccess.ReadWrite);

        using (var accessor = mappedFile.CreateViewAccessor(offset, length))
        {
            int value = 27;
            accessor.Write(0, value);
        }
    }
}

Die zweite Anwendung holt sich nun via MemoryMappedFile.OpenExisting den Shared Memory und schreibt einen anderen Wert hinein:

class Program
{
    static void Main(string[] args)
    {
        using (var mappedFile = MemoryMappedFile.OpenExisting("MappingTest"))
        {
            using (var accessor = mappedFile.CreateViewAccessor())
            {
                var value = 29;
                accessor.Write(0, value);
            }
        }
    }
}

Sobald das Timer-Intervall wieder vergangen ist, sollte der erste Prozess den neuen Wert erhalten.

Et voilá.

Veröffentlicht von Norbert Eder

Ich bin ein leidenschaftlicher Softwareentwickler. Mein Wissen und meine Gedanken teile ich nicht nur hier im Blog, sondern auch in Fachartikeln und Büchern.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Cookie-Einstellungen
Auf dieser Website werden Cookie verwendet. Diese werden für den Betrieb der Website benötigt oder helfen uns dabei, die Website zu verbessern.
Alle Cookies zulassen
Auswahl speichern
Individuelle Einstellungen
Individuelle Einstellungen
Dies ist eine Übersicht aller Cookies, die auf der Website verwendet werden. Sie haben die Möglichkeit, individuelle Cookie-Einstellungen vorzunehmen. Geben Sie einzelnen Cookies oder ganzen Gruppen Ihre Einwilligung. Essentielle Cookies lassen sich nicht deaktivieren.
Speichern
Abbrechen
Essenziell (1)
Essenzielle Cookies werden für die grundlegende Funktionalität der Website benötigt.
Cookies anzeigen