C#内存映射文件学习[转]
内存映射文件是由一个文件到进程地址空间的映射。
C#提供了允许应用程序把文件映射到一个进程的函(MemoryMappedFile.CreateOrOpen)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,只是内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而非系统的页文件,而且在对该文件进行操作之前必须首先对文件进行映射,就如同将整个文件从磁盘加载到内存。由此可以看出,使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。另外,实际工程中的系统往往需要在多个进程之间共享数据,如果数据量小,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法。
共享内存是内存映射文件的一种特殊情况,内存映射的是一块内存,而非磁盘上的文件。共享内存的主语是进程(Process),操作系统默认会给每一个进程分配一个内存空间,每一个进程只允许访问操作系统分配给它的哪一段内存,而不能访问其他进程的。而有时候需要在不同进程之间访问同一段内存,怎么办呢?操作系统给出了创建访问共享内存的API,需要共享内存的进程可以通过这一组定义好的API来访问多个进程之间共有的内存,各个进程访问这一段内存就像访问一个硬盘上的文件一样。而.Net 4.0中引入了System.IO.MemoryMappedFiles命名空间,这个命名空间的类对windows 共享内存相关API做了封装,使.Net程序员可以更方便的使用内存映射文件。
内存映射文件实现进程间通讯
内存映射文件是实现进程通讯的又一种方法,我们可以通过共享剪贴板、共享物理文件来实现进程间的数据共享,这里我们还可以通过内存映射文件来实现共享,这样,文件内的数据就可以用内存读/写指令来访问,而不是用ReadFile和WriteFile这样的I/O系统函数,从而提高了文件存取速度。这种方式更加快捷高效,最适用于需要读取文件并且对文件内包含的信息做语法分析的应用程序,如:对输入文件进行语法分析的彩色语法编辑器,编译器等。这种数据共享是让两个或多个进程映射同一文件映射对象的视图,即它们在共享同一物理存储页。这样,当一个进程向内存映射文件的一个视图写入数据时,其他的进程立即在自己的视图中看到变化。
注意:
对文件映射对象要使用同一名字。
是让两个或多个进程映射同一文件映射对象的视图,即它们在共享同一物理存储页。这样,当一个进程向内存映射文件的一个视图写入数据时,其他的进程立即在自己的视图中看到变化。但要注意,对文件映射对象要使用同一名字。
内存映射文件使用实例:
1. 在同一进程内同时读写同一内存映射文件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.MemoryMappedFiles; namespace UseMMFInProcess
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
CreateMemoryMapFile();
}
private const int FILE_SIZE = ;
/// <summary>
/// 引用内存映射文件
/// </summary>
private MemoryMappedFile memoryFile = null;
/// <summary>
/// 用于访问内存映射文件的存取对象
/// </summary>
private MemoryMappedViewAccessor accessor1, accessor2,accessor;
/// <summary>
/// 创建内存映射文件
/// </summary>
private void CreateMemoryMapFile()
{
try
{
memoryFile = MemoryMappedFile.CreateFromFile("MyFile.dat", FileMode.OpenOrCreate, "MyFile", FILE_SIZE);
//访问文件前半段
accessor1 = memoryFile.CreateViewAccessor(, FILE_SIZE / );
//访问文件后半段
accessor2 = memoryFile.CreateViewAccessor(FILE_SIZE / , FILE_SIZE / );
//访问全部文件
accessor = memoryFile.CreateViewAccessor();
//InitFileContent();
lblInfo.Text = "内存文件创建成功";
ShowFileContents();
}
catch (Exception ex)
{
lblInfo.Text = ex.Message;
}
}
/// <summary>
/// 关闭并释放资源
/// </summary>
private void DisposeMemoryMapFile()
{
if (accessor1 != null)
accessor1.Dispose();
if (accessor2 != null)
accessor2.Dispose();
if (memoryFile != null)
memoryFile.Dispose();
} private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
DisposeMemoryMapFile();
} private void btnWrite1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Length == )
{
lblInfo.Text = "请输入一个字符";
return;
}
char[] chs = textBox1.Text.ToCharArray();
char ch = chs[]; for (int i = ; i < FILE_SIZE / ; i += )
accessor1.Write(i, ch); lblInfo.Text = "字符“" + ch + "”已写到文件前半部份";
ShowFileContents();
} private void btnShow_Click(object sender, EventArgs e)
{
ShowFileContents();
} /// <summary>
/// 初始化文件内容为可视的字符“0”
/// </summary>
private void InitFileContent()
{
for (int i = ; i < FILE_SIZE; i += )
accessor.Write(i,'');
}
/// <summary>
/// 显示文件内容
/// </summary>
private void ShowFileContents()
{
StringBuilder sb = new StringBuilder(FILE_SIZE);
sb.Append("上半段内容:\n"); int j = ;
for (int i = ; i < FILE_SIZE / ; i += )
{
sb.Append("\t");
char ch = accessor.ReadChar(i);
sb.Append(j);
sb.Append(":");
sb.Append(ch);
j++;
}
sb.Append("\n下半段内容:\n"); for (int i = FILE_SIZE / ; i < FILE_SIZE; i += )
{
sb.Append("\t");
char ch = accessor.ReadChar(i);
sb.Append(j);
sb.Append(":");
sb.Append(ch);
j++;
}
richTextBox1.Text = sb.ToString();
} private void btnWrite2_Click(object sender, EventArgs e)
{
if (textBox2.Text.Length == )
{
lblInfo.Text = "请输入一个字符";
return;
}
char[] chs = textBox2.Text.ToCharArray();
char ch = chs[]; for (int i = ; i < FILE_SIZE / ; i += )
accessor2.Write(i, ch);
lblInfo.Text = "字符“" + ch + "”已写到文件后半部份";
ShowFileContents();
}
}
}
2. 使用内存映射文件在进程间传送值类型数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace UseMMFBetweenProcess
{
/// <summary>
/// 要共享的数据结构,注意,其成员不能是引用类型
/// </summary>
public struct MyStructure
{
public int IntValue
{
get;
set;
}
public float FloatValue
{
get;
set;
}
}
} using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.MemoryMappedFiles;
using System.IO; namespace UseMMFBetweenProcess
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
InitMemoryMappedFile();
} /// <summary>
/// 内存映射文件的容量
/// </summary>
private const int FileSize = * ;
private MemoryMappedFile file = null;
private MemoryMappedViewAccessor accessor = null; /// <summary>
/// 初始化内存映射文件
/// </summary>
private void InitMemoryMappedFile()
{
file = MemoryMappedFile.CreateOrOpen("UseMMFBetweenProcess", FileSize);
accessor = file.CreateViewAccessor();
lblInfo.Text = "内存文件创建或连接成功";
} /// <summary>
/// 要共享的数据对象
/// </summary>
private MyStructure data; /// <summary>
/// 显示数据到窗体上
/// </summary>
private void ShowData()
{
textBox1.Text = data.IntValue.ToString();
textBox2.Text = data.FloatValue.ToString();
} /// <summary>
/// 根据用户输入更新数据
/// </summary>
private void UpdateData()
{
data.IntValue = int.Parse(textBox1.Text);
data.FloatValue = float.Parse(textBox2.Text);
} private void btnSave_Click(object sender, EventArgs e)
{
try
{
UpdateData();
accessor.Write<MyStructure>(, ref data);
lblInfo.Text = "数据已经保存到内存文件中";
}
catch (Exception ex)
{
lblInfo.Text = ex.Message;
}
} private void btnLoad_Click(object sender, EventArgs e)
{
accessor.Read<MyStructure>(, out data);
ShowData();
lblInfo.Text = "成功从内存文件中提取了数据";
} private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (accessor != null)
accessor.Dispose();
if (file != null)
file.Dispose();
}
}
}
3. 利用序列化技术通过内存映射文件实现进程通讯
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; namespace UseMMFBetweenProcess2
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
InitMemoryMappedFile();
} /// <summary>
/// 图片
/// </summary>
private Image bmp
{
get
{
return pictureBox1.Image;
}
set
{
pictureBox1.Image = value;
}
} /// <summary>
/// 图片说明
/// </summary>
private string info
{
get
{
return txtImageInfo.Text;
}
set
{
txtImageInfo.Text = value;
}
} private MemoryMappedFile memoryFile = null; private MemoryMappedViewStream stream = null; /// <summary>
/// 最大容量:10M
/// </summary>
private const int FileSize = * * ; /// <summary>
/// 创建内存映射文件,获取其读写流
/// </summary>
private void InitMemoryMappedFile()
{
try
{
memoryFile = MemoryMappedFile.CreateOrOpen("UseMMFBetweenProcess2", FileSize);
stream = memoryFile.CreateViewStream();
}
catch (Exception ex )
{
MessageBox.Show(ex.Message);
Close();
}
}
/// <summary>
/// 释放相关资源
/// </summary>
private void DisposeMemoryMappedFile()
{
if (stream != null)
stream.Close();
if (memoryFile != null)
memoryFile.Dispose();
} private void btnLoadPic_Click(object sender, EventArgs e)
{
ChooseImageFile();
} //选择图片
private void ChooseImageFile()
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
bmp = new Bitmap(openFileDialog1.FileName);
}
}
//根据用户设定的信息创建对象
private MyPic CreateMyPicObj()
{
MyPic obj = new MyPic();
obj.pic = bmp;
obj.picInfo = info;
return obj;
} /// <summary>
/// 将MyPic对象保存到内存映射文件中
/// </summary>
private void SaveToMMF()
{
try
{
MyPic obj = CreateMyPicObj();
IFormatter formatter = new BinaryFormatter();
stream.Seek(, SeekOrigin.Begin);
formatter.Serialize(stream, obj);
MessageBox.Show("对象已保存到内存映射文件中");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} private void LoadFromMMF()
{
try
{
// CreateMyPicObj();
IFormatter formatter = new BinaryFormatter();
stream.Seek(, SeekOrigin.Begin);
MyPic obj = formatter.Deserialize(stream) as MyPic;
if (obj != null)
{
bmp = obj.pic;
info = obj.picInfo;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} private void btnExit_Click(object sender, EventArgs e)
{
Close();
} private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
DisposeMemoryMappedFile();
} private void btnSaveToMMF_Click(object sender, EventArgs e)
{
SaveToMMF();
} private void btnLoadFromMMF_Click(object sender, EventArgs e)
{
LoadFromMMF();
}
}
}
C#内存映射文件学习[转]的更多相关文章
- C#内存映射文件消息队列实战演练(MMF—MQ)
一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...
- Linux下内存映射文件的用法简介
由于项目需要,所以学习了一下Linux下内存映射文件的用法,在这里共享一下自己的收获,希望大家提出宝贵意见,进行交流. 简介: 内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区 ...
- C++中使用内存映射文件处理大文件
引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile() ...
- 《windows核心编程系列》十六谈谈内存映射文件
内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...
- 内存映射文件MemoryMappedFile使用
参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...
- 使用ZwMapViewOfSection创建内存映射文件总结
标 题: [原创]使用ZwMapViewOfSection创建内存映射文件总结 作 者: 小覃 时 间: 2012-06-15,02:28:36 链 接: http://bbs.pediy.com/s ...
- 第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 ...
随机推荐
- HadoopMapReduce运行机制
1.map方法读取一个文件的一行记录进行分析, 输入:LongWritable(当前读取的文件位置), Text(内容) 2.map将读取到的信息进行分类,输入Context (键值对) ;作为 ...
- nagios 安装配置(包含nrpe端)全 (三)
四.系统的配置: 1.介绍 在配置过程中涉及到的几个定义有:主机.主机组,服务.服务组.联系人.联系人组,监控时间.监控命令等. 最重要的有四点: 第一:定义监控哪些主机.主机组.服务和服务组: 第二 ...
- #Virtual hosts #Include conf/extra/httpd-vhosts.conf 开启就不能启动apache
#Virtual hosts#Include conf/extra/httpd-vhosts.conf我只要把其中任何一个开启就是吧#去掉就启动不了apache.怎么回事error.log是这样的ht ...
- Android 通过ADB Wireless无线调试应用
使用数据线调试应用难免不方便,本篇博客介绍使用ADB Wireless工具.当手机和电脑处在同一网络下.实现无线调试应用. ADB Wireless可以让手机用无线来代替USB连接.而使用ADB工具的 ...
- 嵌入式开发之davinci--- 8148/8168/8127 中的图像处理vpss link dei、sclr、swms、Mosaic’s
vpss 中的link (1)dei dei 主要做数据交错处理,带缩放 dei control data flow: (2)sclr 8168中支持缩放按比例的分子和分母,只支持缩小,貌似不支持放大 ...
- Sql数据库查询语言
1.概述 Sql是一种面向数据库的结构化查询语言.是符合美国国家标准化组织ANSI的一种计算机标准语言. Sql具对数据库的操作有:增删改查.创建数据库.创建表.创建存储过程.创建视图等 RDBMS关 ...
- Js_闭包详解
http://blog.csdn.net/chenglc1612/article/details/53413318 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变 ...
- Linux进程间通信——使用信号量【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号 ...
- casperjs userAgent的一些问题
casperjs 的options内的userAgent若设置为非正常浏览器的字符串,可能导致form无法正确提交. 表现为,this.click()失效,或evaluate(function(){$ ...
- MyEclipse8.5优化
MyEclipse8.5优化 第一步: 取消自动validation validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下 ...