MemoryMappedFile 內存映射文件 msdn


http://msdn.microsoft.com/zh-cn/library/dd997372%28v=vs.110%29.aspx

 

內存映射文件

.NET Framework 4.5
其他版本
1(共 1)對本文的評價是有幫助 - 評價此主題

 

內存映射文件包含虛擬內存中文件的內容。 利用文件與內存空間之間的映射,應用程序(包括多個進程)可以通過直接在內存中進行讀寫來修改文件。 從 .NET Framework 4開始,可以使用托管代碼按照本機Windows函數訪問內存映射文件的方式來訪問內存映射文件,如 MSDN Library 中的Managing Memory-Mapped Files in Win32 (管理 Win32 中的內存映射文件)中所述。

有兩種類型的內存映射文件:

  • 持久內存映射文件

    持久文件是與磁盤上的源文件關聯的內存映射文件。 在最后一個進程使用完此文件后,數據將保存到磁盤上的源文件中。 這些內存映射文件適合用來處理非常大的源文件。

  • 非持久內存映射文件

    非持久文件是未與磁盤上的源文件關聯的內存映射文件。 當最后一個進程使用完此文件后,數據將丟失,並且垃圾回收功能將回收此文件。 這些文件適用於為進程間通信 (IPC) 創建共享內存。

內存映射文件可以在多個進程之間進行共享。 進程可以通過使用由創建同一內存映射文件的進程所指派的公用名來映射到此文件。

若要使用一個內存映射文件,則必須創建該內存映射文件的完整視圖或部分視圖。 還可以創建內存映射文件的同一部分的多個視圖,進而創建並發內存。 為了使兩個視圖能夠並發,必須基於同一內存映射文件創建這兩個視圖。

如果文件大於應用程序用於內存映射的邏輯內存空間(在 32 位計算機上為 2 GB),則還需要使用多個視圖。

有兩種類型的視圖:流訪問視圖和隨機訪問視圖。 使用流訪問視圖可對文件進行順序訪問;對於非持久文件和 IPC,這是建議的方法。 在使用持久文件時,隨機訪問視圖是首選方法。

由於內存映射文件是通過操作系統的內存管理器訪問的,因此會自動將此文件分隔為多個頁,並根據需要對其進行訪問。 您不需要自行處理內存管理。

下圖演示多個進程如何同時具有對同一內存映射文件的多個重疊視圖。

內存映射文件的多個重疊視圖

顯示內存映射文件的視圖。

下表提供有關使用內存映射文件對象及其成員的指南。

 

任務

使用的方法或屬性

從磁盤上的文件中獲取表示持久內存映射文件的 MemoryMappedFile 對象。

MemoryMappedFile.CreateFromFile 方法。

獲取表示非持久內存映射文件(與磁盤上的文件不關聯)的 MemoryMappedFile 對象。

MemoryMappedFile.CreateNew 方法。

- 或 -

MemoryMappedFile.CreateOrOpen 方法。

獲取現有內存映射文件(持久文件或非持久文件)的 MemoryMappedFile 對象。

MemoryMappedFile.OpenExisting 方法。

獲取針對內存映射文件的順序訪問視圖的 UnmanagedMemoryStream 對象。

MemoryMappedFile.CreateViewStream 方法。

獲取針對內存映射文件的隨機訪問視圖的 UnmanagedMemoryAccessor 對象。

MemoryMappedFile.CreateViewAccessor 方法。

獲取要用於非托管代碼的 SafeMemoryMappedViewHandle 對象。

MemoryMappedFile.SafeMemoryMappedFileHandle 屬性。

- 或 -

MemoryMappedViewAccessor.SafeMemoryMappedViewHandle 屬性。

- 或 -

MemoryMappedViewStream.SafeMemoryMappedViewHandle 屬性。

將內存分配推遲到創建視圖后進行(僅限於非持久文件)。

(若要確定當前系統頁大小,請使用 Environment.SystemPageSize 屬性。)

MemoryMappedFileOptions.DelayAllocatePages 值的 CreateNew 方法。

- 或 -

MemoryMappedFileOptions 枚舉作為參數的 CreateOrOpen 方法。

Dd997372.collapse_all(zh-cn,VS.110).gif安全性

在創建內存映射文件時,可以通過使用以下方法(這些方法采用 MemoryMappedFileAccess 枚舉作為參數)來應用訪問權限:

通過使用將 MemoryMappedFileRights 用作參數的 OpenExisting 方法,可以指定用於打開現有內存映射文件的訪問權限。

此外,可以包含一個 MemoryMappedFileSecurity 對象,該對象包括預定義的訪問規則。

若要將新的或已更改的訪問規則應用於內存映射文件,請使用 SetAccessControl 方法。 若要從現有文件中檢索訪問規則或審核規則,請使用 GetAccessControl 方法。

Dd997372.collapse_all(zh-cn,VS.110).gif持久內存映射文件

CreateFromFile 方法基於磁盤上的現有文件創建一個內存映射文件。

下面的示例創建一個特大文件的某一部分的內存映射視圖,並操作該文件的某一部分。

C#
VB
 
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);
    }
}


下面的示例為另一個進程打開同一內存映射文件。

C#
VB
 
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);
    }
}


Dd997372.collapse_all(zh-cn,VS.110).gif非持久內存映射文件

CreateNew CreateOrOpen 方法創建一個未映射到磁盤上的現有文件的內存映射文件。

下面的示例由三個單獨的進程(控制台應用程序)組成,這些進程將布爾值寫入到內存映射文件中。 將發生下面一系列操作:

  1. Process A 創建內存映射文件並將一個值寫入到其中。

  2. Process B 打開內存映射文件並將一個值寫入到其中。

  3. Process C 打開內存映射文件並將一個值寫入到其中。

  4. Process A 讀取並顯示內存映射文件中的值。

  5. Process A 使用完內存映射文件后,垃圾回收功能將會立即回收該文件。

若要運行此示例,請執行以下步驟:

  1. 編譯應用程序並打開三個命令提示符窗口。

  2. 在第一個命令提示符窗口中,運行 Process A

  3. 在第二個命令提示符窗口中,運行 Process B

  4. 返回到 Process A 並按 Enter。

  5. 在第三個命令提示符窗口中,運行 Process C

  6. 返回到 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

C#
VB
 
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: {0}", reader.ReadBoolean());
                Console.WriteLine("Process B says: {0}", reader.ReadBoolean());
                Console.WriteLine("Process C says: {0}", reader.ReadBoolean());
            }
            mutex.ReleaseMutex();
        }
    }
}


進程 B

C#
VB
 
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.");
        }
    }
}


進程 C

C#
VB
 
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.");
        }
    }
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM