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 方法。

安全性

在创建内存映射文件时,可以通过使用以下方法(这些方法采用 MemoryMappedFileAccess 枚举作为参数)来应用访问权限:

通过使用将 MemoryMappedFileRights 用作参数的 OpenExisting 方法,可以指定用于打开现有内存映射文件的访问权限。

此外,可以包含一个 MemoryMappedFileSecurity 对象,该对象包括预定义的访问规则。

若要将新的或已更改的访问规则应用于内存映射文件,请使用 SetAccessControl 方法。
若要从现有文件中检索访问规则或审核规则,请使用 GetAccessControl 方法。

示例

 

持久内存映射文件

CreateFromFile
方法基于磁盘上的现有文件创建一个内存映射文件。

下面的示例创建一个特大文件的某一部分的内存映射视图,并操作该文件的某一部分。

 
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);
}
}

下面的示例为另一个进程打开同一内存映射文件。

 
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);
}
}

非持久内存映射文件

CreateNewCreateOrOpen 方法创建一个未映射到磁盘上的现有文件的内存映射文件。

下面的示例由三个单独的进程(控制台应用程序)组成,这些进程将布尔值写入到内存映射文件中。 将发生下面一系列操作:

  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

 
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

 
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

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

MemoryMappedFile 内存映射文件 msdn的更多相关文章

  1. 内存映射文件MemoryMappedFile使用

    参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...

  2. NET 4 中 内存映射文件

    原文链接 : http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net- ...

  3. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转

    原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing ...

  4. Java利用内存映射文件实现按行读取文件

    我们知道内存映射文件读取是各种读取方式中速度最快的,但是内存映射文件读取的API里没有提供按行读取的方法,需要自己实现.下面就是我利用内存映射文件实现按行读取文件的方法,如有错误之处请指出,或者有更好 ...

  5. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped

    节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作 ...

  6. .NET 4.0中使用内存映射文件实现进程通讯

    操作系统很早就开始使用内存映射文件(Memory Mapped File)来作为进程间的共享存储区,这是一种非常高效的进程通讯手段.Win32 API中也包含有创建内存映射文件的函数,然而,这些函数都 ...

  7. C#内存映射文件消息队列实战演练(MMF—MQ)

    一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...

  8. Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收

    之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧. 之前课本上说的进程间通信,有共享内存.管道等之类的,但没有自己操刀写过 ...

  9. C#内存映射文件学习[转]

    原文链接 内存映射文件是由一个文件到进程地址空间的映射. C#提供了允许应用程序把文件映射到一个进程的函(MemoryMappedFile.CreateOrOpen).内存映射文件与虚拟内存有些类似, ...

随机推荐

  1. 类的本质、description方法、SEL、NSLog输出增强

    一.类的本质 1.类也是个对象 其实类也是一个对象,是Class类型的对象,简称“类对象” Class类型的定义 typedef struct objc_class *Class; 类名就代表着类对象 ...

  2. shell 实现word count

    awk '{arr[$2]+=$1}END{for (i in arr) print i,arr[i]}' sort_all.txt | sort -k2nr -g

  3. ExtJS4.2学习(20)动态数据表格之前几章总结篇1(转)

    鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2014-02-18/196.html --------------- ...

  4. 【扩展欧几里得】Bzoj 1477:青蛙的约会

    Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事 ...

  5. uva 567

    Floyd 算法   就输入麻烦点 #include <iostream> #include <cstring> #include <cstdlib> #inclu ...

  6. Stretch a row if data overflows in jasper reports

    My band stretches if necessary with the following conditions, I do not know yours. I have started wi ...

  7. 李洪强iOS开发之使用 Reachability 检测网络

    1.iOS平台是按照一直有网络连接的思路来设计的,开发者利用这一特点创造了很多优秀的第三方应用. 大多数的iOS应用都需要联网,甚至有些应用严重依赖网络,没有网络就无法正常工作. 2.在你的应用尝试通 ...

  8. 版本管理工具介绍—Git篇

    前篇 如题,提起版本管理工具相信做C#开发 还是对Git比较陌生  我们可能更熟悉vss.svn 记录此文的目的 更是为以后的前段学习做基础  现在的技术比如nodeJs  angularJs ==都 ...

  9. ORA-00911 :无效字符

    ———————————————————————————————————————————————————— 附: 1   ORA-01790:表达式必须具有与对应表达式相同的数据类型 知识解析:SQL ...

  10. Oracle 学习笔记 常用查询命令篇

    1.查询某个用户下有多少张表 有时候很有用  select count(*) from dba_tables t where t.owner='SCOTT';