操作系统很早就开始使用内存映射文件(Memory Mapped File)来作为进程间的共享存储区,这是一种非常高效的进程通讯手段。.NET 4.0新增加了一个System.IO. MemoryMappedFiles命名空间,其中添加了几个类和相应的枚举类型,从而使我们可以很方便地创建内存映射文件。Mono 3.2也有这个类来操作Linux下的内存映射文件,《MemoryMappedFile 在 Mono in Linux 的开发笔记》详细的介绍了Mono和.NET 4的实现区别,为了让代码能够在Linux和Windows平台都正常运行,建议统一使用

MemoryMappedFile.CreateFromFile(
    FileStream fileStream,
    String mapName,
    Int64 capacity,
    MemoryMappedFileAccess access,
    System.IO.MemoryMappedFiles.MemoryMappedFileSecurity memoryMappedFileSecurity,
    HandleInheritability inheritability,
    Boolean leaveOpen
)

方法来创建MMF,并且在调用前确保指定的文件流大小与capacity参数值相同。

下面我给出在Windows和Linux下都运行正常的代码:

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
using System.Text;
using System.Security.AccessControl;
using System.Configuration;

namespace ManagedMMF
{
    class Program
    {
        static void Main(string[] args)
        {
            // Build a sample object and report records
            HikingDatabase hikingData = BuildDatabase(5000, 50);
            Console.WriteLine("Dummy database object created with " + hikingData.hikes.Length + " records.");
            string mmfile = ConfigurationManager.AppSettings["mmf"];
            // Write object to MMF
            WriteObjectToMMF(mmfile, hikingData);

            // Clear object and report
            hikingData = null;
            Console.WriteLine("Database object has been destroyed.");

            // Read new object from MMF and report records
            hikingData = ReadObjectFromMMF(mmfile) as HikingDatabase;
            Console.WriteLine("Dummy database object re-loaded from MMF with " + hikingData.hikes.Length + " records.");

            // Wait for input and terminate
            Console.ReadLine();
        }

        #region Generic MMF read/write object functions

        static void WriteObjectToMMF(string mmfFile, object objectData)
        {
            string mapName = "MyFile";
            if (IsMono())
            {
                mapName = mmfFile;
            }
            // Convert .NET object to byte array
            byte[] buffer = ObjectToByteArray(objectData);
            using (FileStream fs = new FileStream(mmfFile, FileMode.Create, FileAccess.ReadWrite))
            {
                fs.SetLength(buffer.Length);
                // Create a new memory mapped file
                using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(fs, mapName, buffer.Length,
                    MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity() { }, HandleInheritability.Inheritable, true))
                {
                    // Create a view accessor into the file to accommmodate binary data size
                    using (MemoryMappedViewAccessor mmfWriter = mmf.CreateViewAccessor(0, buffer.Length))
                    {
                        // Write the data
                        mmfWriter.WriteArray<byte>(0, buffer, 0, buffer.Length);
                    }
                }
            }
        }

        static object ReadObjectFromMMF(string mmfFile)
        {
            string mapName = "MyFile";
            if (IsMono())
            {
                mapName = mmfFile;
            }
            using (FileStream fs = new FileStream(mmfFile, FileMode.Open, FileAccess.ReadWrite))
            {
                // Get a handle to an existing memory mapped file
                using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(fs, mapName, fs.Length,
                    MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity() { }, HandleInheritability.Inheritable, true))
                {
                    // Create a view accessor from which to read the data
                    using (MemoryMappedViewAccessor mmfReader = mmf.CreateViewAccessor())
                    {
                        // Create a data buffer and read entire MMF view into buffer
                        byte[] buffer = new byte[mmfReader.Capacity];
                        mmfReader.ReadArray<byte>(0, buffer, 0, buffer.Length);

                        // Convert the buffer to a .NET object
                        return ByteArrayToObject(buffer);
                    }
                }
            }
        }

        static bool IsMono()
        {
            Type t = Type.GetType("Mono.Runtime");
            return t != null;
        }

        #endregion

        #region Object/Binary serialization

        static object ByteArrayToObject(byte[] buffer)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();    // Create new BinaryFormatter
            MemoryStream memoryStream = new MemoryStream(buffer);       // Convert byte array to memory stream, set position to start
            return binaryFormatter.Deserialize(memoryStream);           // Deserializes memory stream into an object and return
        }

        static byte[] ObjectToByteArray(object inputObject)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();    // Create new BinaryFormatter
            MemoryStream memoryStream = new MemoryStream();             // Create target memory stream
            binaryFormatter.Serialize(memoryStream, inputObject);       // Convert object to memory stream
            return memoryStream.ToArray();                              // Return memory stream as byte array
        }

        #endregion

        static HikingDatabase BuildDatabase(int recordCount, int gpsCoordCount)
        {
            Random rand = new Random();

            HikingDatabase hikingData = new HikingDatabase();
            hikingData.Description = "My hikes, 2010 to 2012";
            hikingData.hikes = new Hike[recordCount];
            for (int i = 0; i < hikingData.hikes.Length; i++)
            {
                hikingData.hikes[i] = new Hike();
                hikingData.hikes[i].Description = "This is a description of this particular record. ";
                hikingData.hikes[i].Date = DateTime.Now.ToLongDateString();
                hikingData.hikes[i].GPSTrack = new Coord[gpsCoordCount];
                for (int j = 0; j < hikingData.hikes[i].GPSTrack.Length; j++)
                {
                    hikingData.hikes[i].GPSTrack[j] = new Coord();
                    hikingData.hikes[i].GPSTrack[j].x = rand.NextDouble() * 1000000;
                    hikingData.hikes[i].GPSTrack[j].y = rand.NextDouble() * 1000000;
                    hikingData.hikes[i].GPSTrack[j].z = rand.NextDouble() * 1000;
                }
            }
            return hikingData;
        }
    }

    #region Sample object for I/O

    [Serializable]
    public class HikingDatabase
    {
        public string Description;
        public Hike[] hikes;
    }

    [Serializable]
    public class Hike
    {
        public string Description;
        public string Date;
        public Coord[] GPSTrack;
    }

    [Serializable]
    public class Coord
    {
        public double x;
        public double y;
        public double z;
    }
    #endregion
}
    所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特定的文件相对应。进程将这块内存区域映射到自己的地址空间中,访问它就象是访问普通的内存一样。
在.NET中,使用MemoryMappedFile对象表示一个内存映射文件,通过它的CreateFromFile()方法根据磁盘现有文件创建内存映射文件,调用这一方法需要提供一个与磁盘现有文件相对应的FileStream对象。
当MemoryMappedFile对象创建之后,我们并不能直接对其进行读写,必须通过一个MemoryMappedViewAccessor对象来访问这个内存映射文件。MemoryMappedFile. CreateViewAccessor()方法可以创建MemoryMappedViewAccessor对象,而此对象提供了一系列读写的方法,用于向内存映射文件中读取和写入数据。
在创建内存映射文件访问对象需要指定它所能访问的内存映射文件的内容范围,这个“范围”称为“内存映射视图(Memory Mapped View)”。可以将它与“放大镜”类比,当使用一个放大镜阅读书籍时,一次只能放大指定部分的文字。类似地,我们只能在内存映射视图所规定的范围内存取内存映射文件。
如果要向内存映射文件中序列化对象,必须将内存映射文件转换为可顺序读取的流。幸运的是,MemoryMappedFile类的CreateViewStream()方法可以创建一个MemoryMappedViewStream对象,通过它即可序列化对象。这个对象允许序列访问映射视图;这个可能是使用映射视图流(mapped view streams)与使用允许随即访问的accessor对象相比的最大缺点。

A quick (low-latency) IPC channel for .NET (Using MemoryMappedFile and Event)https://github.com/geffzhang/QuickIPC
相关文章: 
Memory Mapped File Interoperability with .NET Objects
Programming Memory-Mapped Files with the .NET Framework
.Net Framework 4.0開始有包好的MemoryMappedFile的類別了
Working with memory mapped files in .NET 4
MemoryMappedFile 在 Mono in Linux 的开发笔记
MemoryMappedFile使用小结
System.IO之内存映射文件共享内存

https://github.com/geffzhang/QuickIPC

在Linux和Windows平台上操作MemoryMappedFile(简称MMF)的更多相关文章

  1. 如何在微软Windows平台上打造出你的Linux开发环境(转载)

    如何在微软Windows平台上打造出你的Linux开发环境 投递人 itwriter 发布于 2013-12-10 11:18 评论(1) 有348人阅读  原文链接  [收藏]  « » 英文原文: ...

  2. 在Windows平台上安装Node.js及NPM模块管理

    1. 下载Node.js官方Windows版程序:http://nodejs.org/#download    从0.6.1开始,Node.js在Windows平台上提供了两种安装方式,一是.MSI安 ...

  3. 分享一些 Windows 平台上的神器

    下面分享一些 Windows 平台上日常开发使用的软件,有些软件我自认为是神器,可以大大提高效率. 编辑器类软件 IntelliJ IDEA IntelliJ IDEA 内部集成 Java 开发环境, ...

  4. MySQL&#160;在Windows平台上的安装及实例多开

    MySQL在Windows平台上的安装及实例多开   by:授客 QQ:1033553122 测试环境 Win7 64 mysql-5.7.20-winx64.zip 下载地址: https://cd ...

  5. 在Linux和Windows系统上安装Nginx服务器的教程

    在Linux和Windows系统上安装Nginx服务器的教程  1.在CentOS系统上安装Nginx 在 CentOS6 版本的 EPEL 源中,已经加入了 nginx 的 rpm 包,不过此 RP ...

  6. Windbg是windows平台上强大的调试器

    基础调试命令 - .dump/.dumpcap/.writemem/!runaway Windbg是windows平台上强大的调试器,它相对于其他常见的IDE集成的调试器有几个重要的优势, Windb ...

  7. 国密SM3算法在linux和windows平台结果不一致问题

    什么是sm3,是一种类似于sha256的哈希算法,是咱们国家的哈希标准算法: 最近在使用sm3算法时,同样的一份数据,调用同样的sm3接口,发现得到的结果是不一样的: 那么在应用过的过程中,如果同样的 ...

  8. 在windows平台上构建自己的PHP(php5.3+)

    这是一篇翻译的文章,原文参见:https://wiki.php.net/internals/windows/stepbystepbuild 顺便提一句,wiki.php.net有很多精彩的内容,想深入 ...

  9. 【摘录】在Windows平台上使用Objective-C

    虽然到目前为止最好的Objective-C 编码平台来自苹果公司,但它们绝不仅适用于苹果公司的平台.Objective-C 在Linux.BSD 甚至Windows 等其他平台都有相当久远的历史.根据 ...

随机推荐

  1. js实现前端分页页码管理

    用JS实现前端分页页码管理,可以很美观的区分页码显示(这也是参考大多数网站的分页页码展示),能够有很好的用户体验,这也是有业务需要就写了一下,还是新手,经验不足,欢迎指出批评! 首先先看效果图: 这是 ...

  2. javascript技术难点(三)之this、new、apply和call详解

    4)    this.new.call和apply的相关问题 讲解this指针的原理是个很复杂的问题,如果我们从javascript里this的实现机制来说明this,很多朋友可能会越来越糊涂,因此本 ...

  3. loj 1156(二分+最大流)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26870 思路:由于溢出问题,wa了半天,还以为构图错了呢,查了半天 ...

  4. Feature Engineering versus Feature Extraction: Game On!

    Feature Engineering versus Feature Extraction: Game On! "Feature engineering" is a fancy t ...

  5. Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十六)

    今天我们继续实验Bridge方式的网络配置. Bridge的逻辑原理图如下: 上图中的“br0”就充当了一个桥的作用,主机上的物理网口eth0等根据需要加入到这个桥里面,所有虚拟机要跟外界通信都通过这 ...

  6. 2014 CSDN博文大赛终于获奖名单发布

    博文大赛第二阶段(2014年7月15日-2014年8月10日)已经结束,决赛获奖名单已在8月11日出炉. 现将获奖名单发布: 移动开发 NO.1    罗升阳    Luoshengyang    S ...

  7. 电脑用bat脚本给手机批量自动安装apk文件 autoInstall.bat

    ------创建这个文件autoInstall.bat 内容如下: @ECHO off @REM 将adb.exe添加到PATH中ECHO 初始化…@SET PATH=%PATH%;%CD%\Adb@ ...

  8. tomcat 查看和修改内存

    为了解决tomcat在大进行大并发请求时,出现内存溢出的问题,请修改tomcat的内存大小,其中分为以下两种方式: 一.使用 catalina.bat 等命令行方式运行的 tomcat 查看系统最大支 ...

  9. Kafka记录-常用命令选项说明

    1.kafka-topics  主题 如:kafka-topics --create --zookeeper 10.0.4.142:2181/kafka --replication-factor 1 ...

  10. 【译】第18节---数据注解-ForeignKey

    原文:http://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-fi ...