NET 4 中 内存映射文件
原文链接 : http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx
预备知识 : 本文需要你对 OS 内存管理有一定了解。
我想探索下即将到来的 .NET 4 中一些与众不同的新特性,而不是已被大众所熟知的动态类型、协变与逆变等特性。出于对性能增强的喜爱,接下来俺将发表几篇新特性的博文。
内存映射文件对于托管世界的开发人员来说,似乎就像是火星人一样陌生(画外音 : 还是回火星吧,地球上很危险嘀)。但是它确实已经行之经年,毫不客气的说,它在 OS 中的地位相当重要。实际上,任何想要共享数据的通信模型都会在幕后使用它。
那么内存映射文件究竟是个什么玩意呢?内存映射文件允许你保留一块地址空间,然后提交物理存储到这块空间(嗯,听起来是不是很像虚拟内存?)。这哥俩最主要的区别就在于物理存储来自于磁盘上已有的文件,而不是内存管理器。这样做有两大意图 :
1.访问磁盘文件上的数据不需要执行文件 I/O 操作和缓存文件内容。当你访问超大型文件数据时,作用尤其显著。 2.你能使用内存映射文件让运行在同一台机器上的多个进程共享彼此数据。
译注 : Windows 操作系统自身就使用内存映射来执行 DLL,并装载和执行 EXE 文件。
内存映射文件是单一机器多进程间数据通信的最高效的方式。此外,如果你参考其他 IPC 方法,就会看到如下图所示的架构 :
Woo…,现在你对该技术的强大威力有个大概印象了吧(在 System.IO 命名空间下,它甚至可以完全替代 P/Invoke 技术)。
现在,让我来快速解释下它如何工作。我们有两种内存映射文件模型。一个呢,就是使用自定义文件。它可以是应用程序想要访问的任意文件。另一个呢,则是页面文件。我们将和内存管理器一块共享它(这是最常用的技术模型)。
先来介绍下自定义文件模型。首先我们要做的事就是为我们要使用的文件创建一个 FileStream,它可以是已有的文件或者新文件(记住,你应该以共享方式打开这个文件,否则其他进程就无法访问它)。创建合适的流之后,现在就可以创建内存映射文件了。如下所示 :
这里,我使用了 MemoryMappedFile 类的一个特简单的构造函数。我们定义了要用到的流,然后给内存映射文件起了个名字。此外,我们还需要知道内存映射文件的大小(按字节计)和访问的类型。这样,我们就创建了一个内存映射文件。但是在开始使用它之前,我们还需要一个映射视图。接下来,我们就来创建它 :
这个映射覆盖了整个文件。如果我们现在就要从内存映射文件读或写信息,只需要调用带有正确偏移量的映射视图方法就行了。
我们可以往任何内置类型或带有泛型约束的自定义类型写入数据。内存映射文件有个很好的特性就是持久性。在你关闭它之前,里面的内容都会堆积在磁盘上。这对于应用程序间共享缓存信息非常有用。
Well,其它进程如何读取该内存映射文件的内容呢。一样,我们先创建一个内存映射文件。不过我们用的是另外的构造函数,以打开已有的内存映射文件。如果不存在,再新建也不迟。译注 : 原文中的代码示例是错误的。
接下来创建映射视图来读取信息,如下所示 :
看,是不是很简单?但是这种方法有个小小的缺点,这和内存映射文件的大小有关。如果事先不知道大小的话,为了以防万一,你可能会构造一个超级大的文件。可是这样就浪费了大量的地址空间。毕竟你保留的地址远比你提交的物理空间要大,不是吗?
为了解决这个问题,我们可以使用页面文件。这对于百忙中提交数据非常有利。但同时也引入了一个新问题 : 你不会拥有自己的文件,而且映射会一直持续到最后的句柄销毁之后。不过仔细想想,这种方案挺合理的。
现在我们重新构造下前面的示例。这次,我将使用最完整参数的构造函数,这样还可以介绍一些其他的特性。当然,这些特性同样适用于自定义文件。
MemoryMappedFileSecurity 类允许你自定义哪个进程可以访问资源。当你想要保护敏感信息时,或者你不想其他进程改变此内存映射文件时,这个特性非常有用。你可以查看这个对象所有你想要改变的不同设置。在这里你可以获得更详细的信息。如果我们想要探究内存映射文件结构的话,不需要构造一个流,只要找到该资源的名字即可。这会把映射名称和基于文件大小的区域链接起来。如此多个进程间就知道如何访问文件了。注意,使用 DelayAllocatePages 属性后,只有在必要的时候才会预留/提交地址空间。最后一个有意思的参数就是句柄继承模型了。它允许在必要的时候,可以喝子进程共享资源。
如何访问文件就跟前述的示例一样了。千万记住,如果你关闭了内存映射文件,那么它就不能访问了。这个问题困扰了很多开发人员。
最后,让我们来看一下另外一个有意思的领域 : 创建多个映射视图。它们同时工作访问同一个内存映射文件的不同区域。这个时候你就得适当保护内容和同步访问。
我们可以定义不同的偏移量和长度来创建自己的映射视图。如下所示 :
现在你可以享受 .NET 4.0 所带来的高性能数据共享模型的强大威力了。注意,本文基于 .NET 4.0 BETA1 创作。
译注 : UNIX 没有使用映射文件来实现内存共享,它有显式的内存共享 API 函数。这些函数式 shmget、shmctl、shmat、shmdt,以及 mmap、munmap。最后两个函数虽然跟本文所讲的有点类似,但是它们没有映射对象。
NET 4 中 内存映射文件的更多相关文章
- .NET 4.0中使用内存映射文件实现进程通讯
操作系统很早就开始使用内存映射文件(Memory Mapped File)来作为进程间的共享存储区,这是一种非常高效的进程通讯手段.Win32 API中也包含有创建内存映射文件的函数,然而,这些函数都 ...
- C++中使用内存映射文件处理大文件
引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile() ...
- Delphi 中内存映射对于大文件的使用
这篇文章主要介绍了Delphi 中内存映射对于大文件的使用的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下 Delphi 中内存映射对于大文件的使用 平时很少使用大文件的内存映射,碰巧遇到了 ...
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案
C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...
- 内存映射文件MemoryMappedFile使用
参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...
- python 中内存映射二进制文件
内存映射一个文件并不会导致整个文件被读取到内存中. 也就是说,文件并没有被复制到内存缓存或数组中.相反,操作系统仅仅为文件内容保留了一段虚拟内存. 当你访问文件的不同区域时,这些区域的内容才根据需要被 ...
- 第17章 内存映射文件(3)_稀疏文件(Sparse File)
17.8 稀疏调拨的内存映射文件 17.8.1 稀疏文件简介 (1)稀疏文件(Sparse File):指的是文件中出现大量的0数据,这些数据对我们用处不大,但是却一样的占用空间.NTFS文件系统对此 ...
- 《Java核心技术卷二》笔记(二)文件操作和内存映射文件
文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...
- 内存映射文件详解-----C++实现
先不说内存映射文件是什么.贴个代码先,. #include <iostream> #include <fcntl.h> #include <io.h> #inclu ...
随机推荐
- GitHub18
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...
- Activiti中子流程:SubProcess,CallActiviti的区别
子流程:SubProcess,CallActiviti的区别 https://community.alfresco.com/thread/221771-call-activiti-vs-subproc ...
- OSI的七层模型介绍
应用层: 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层: 数据格式化,代码转换,数据加密 没有协议. (信息的语法语义以及它们的 ...
- PSP(5.11——5.17)以及周记录
1.PSP 5.11 14:30 20:00 130 200 Cordova A Y min 5.12 9:00 14:00 100 200 Cordova A Y min 5.13 13:30 15 ...
- spss入门
spss下载地址:http://www.ddooo.com/softdown/53379.htm
- python中常用的九种数据预处理方法分享
Spyder Ctrl + 4/5: 块注释/块反注释 本文总结的是我们大家在python中常见的数据预处理方法,以下通过sklearn的preprocessing模块来介绍; 1. 标准化(St ...
- datetime的小坑
在做悦运动这个项目时,在创建约运动关系表时,运动开始时间,注意(导入datetime包时,我导入的是class datetime(__datetime.date)这个类,可以调用这个类中的方法,调用当 ...
- Delphi7/2007/2009/2010/XE/XE2/XE3/XE4/XE5/XE6/XE7/XE8/10最终版
RAD Studio 10.1 Berlin(with Update1)http://altd.embarcadero.com/download/radstudio/10.1/delphicbuild ...
- LODOP选择路径,保存写入word文件
之前的博文介绍了lodop和c-lodop如果使用 LODOP.GET_DIALOG_VALUE弹出对话框,让用户选择路径,例如保存文件的路径,这样用户就不用手动输入想要的路径. 这一篇,是利用上一篇 ...
- jenkins--svn+Email自动触发1(作业设置)
项目名称设置: svn设置: 触发构建设置: 构建加入sonar-scanner代码扫描: 邮件设置: 邮件触发器配置: