C#.Net通信共享内存映射文件是什么
这篇文章主要讲解了“C#.Net通信共享内存映射文件是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#.Net通信共享内存映射文件是什么”吧!
节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。
内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当。实际上,任何想要共享数据的通信模型都会在幕后使用它。
内存映射文件究竟是个什么?
内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作。物理存储是文件管理,而内存映射文件是操作系统级内存管理。
优势:
1.访问磁盘文件上的数据不需执行I/O操作和缓存操作(当访问文件数据时,作用尤其显著);
2.让运行在同一台机器上的多个进程共享数据(单机多进程间数据通信效率最高);
利用文件与内存空间之间的映射,应用程序(包括多个进程)可以通过直接在内存中进行读写来修改文件。.NET Framework 4 用托管代码按照本机Windows函数访问内存映射文件的方式来访问内存映射文件,管理 Win32 中的内存映射文件。
有两种类型的内存映射文件:
持久内存映射文件
持久文件是与磁盘上的源文件关联的内存映射文件。在最后一个进程使用完此文件后,数据将保存到磁盘上的源文件中。这些内存映射文件适合用来处理非常大的源文件。
非持久内存映射文件
非持久文件是未与磁盘上的源文件关联的内存映射文件。当最后一个进程使用完此文件后,数据将丢失,并且垃圾回收功能将回收此文件。这些文件适用于为进程间通信(IPC) 创建共享内存。
1)在多个进程之间进行共享(进程可通过使用由创建同一内存映射文件的进程所指派的公用名来映射到此文件)。
2)若要使用一个内存映射文件,则必须创建该内存映射文件的完整视图或部分视图。还可以创建内存映射文件的同一部分的多个视图,进而创建并发内存。为了使两个视图能够并发,必须基于同一内存映射文件创建这两个视图。
3)如果文件大于应用程序用于内存映射的逻辑内存空间(在 32 位计算机上为2GB),则还需要使用多个视图。
有两种类型的视图:流访问视图和随机访问视图。使用流访问视图可对文件进行顺序访问;在使用持久文件时,随机访问视图是首选方法。
.Net 共享内存 内存映射文件原理
通过操作系统的内存管理器访问的,因此会自动将此文件分隔为多个页,并根据需要对其进行访问。您不需要自行处理内存管理。如下图:
C# .Net 共享内存 演示代码
//持久内存映射文件:基于现有文件创建一个具有指定公用名的内存映射文件using(varmmf=MemoryMappedFile.CreateFromFile(@"c:\内存映射文件.data",FileMode.Open,"公用名")){//通过指定的偏移量和大小创建内存映射文件视图服务器using(varaccessor=mmf.CreateViewAccessor(offset,length))//偏移量,可以控制数据存储的内存位置;大小,用来控制存储所占用的空间{//Marshal提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。intsize=Marshal.SizeOf(typeof(char));//修改内存映射文件视图for(longi=0;i<length;i+=size){charc=accessor.ReadChar(i);accessor.Write(i,refc);}}}//另一个进程或线程可以,在系统内存中打开一个具有指定名称的现有内存映射文件using(varmmf=MemoryMappedFile.OpenExisting("公用名")){using(varaccessor=mmf.CreateViewAccessor(4000000,2000000)){intsize=Marshal.SizeOf(typeof(char));for(longi=0;i<length;i+=size){charc=accessor.ReadChar(i);accessor.Write(i,refc);}}}
//非持久内存映射文件:未映射到磁盘上的现有文件的内存映射文件using(MemoryMappedFilemmf=MemoryMappedFile.CreateNew("testmap",10000)){boolmutexCreated;//进程间同步Mutexmutex=newMutex(true,"testmapmutex",outmutexCreated);using(varstream=mmf.CreateViewStream())//创建文件内存视图流基于流的操作{varwriter=newBinaryWriter(stream);writer.Write(1);}mutex.ReleaseMutex();Console.WriteLine("StartProcessBandpressENTERtocontinue.");Console.ReadLine();mutex.WaitOne();using(MemoryMappedViewStreamstream=mmf.CreateViewStream()){varreader=newBinaryReader(stream);Console.WriteLine("ProcessAsays:{0}",reader.ReadBoolean());Console.WriteLine("ProcessBsays:{0}",reader.ReadBoolean());}mutex.ReleaseMutex();}using(MemoryMappedFilemmf=MemoryMappedFile.OpenExisting("testmap")){Mutexmutex=Mutex.OpenExisting("testmapmutex");mutex.WaitOne();using(varstream=mmf.CreateViewStream(1,0))//注意这里的偏移量{varwriter=newBinaryWriter(stream);writer.Write(0);}mutex.ReleaseMutex();}
C# .Net 进程间通信共享内存
完整示例:C#共享内存非持久化方式通讯的例子,通讯时的线程和进程控制也没有问题。
先启动消息服务IMServer_Message,
再启动状态服务IMServer_State,
IMServer_Message回车一次(创建共享内存公用名和公用线程锁,并视图流方式写共享内存),
IMServer_State回车一次(获取共享内存并视图流方式写、视图访问器写入结构体类型)
并立刻IMServer_Message再回车一次(读取刚刚写入的信息),
观察IMServer_State屏显变化并等待(线程锁)约5s(线程锁被释放)后
在IMServer_Message上观察屏显(显示刚刚写入共享内存的信息)
IMServer_Message.exe 代码
usingSystem;usingSystem.IO;usingSystem.IO.MemoryMappedFiles;usingSystem.Runtime.InteropServices;usingSystem.Threading;namespaceIMServer_Message{///<summary>///用于共享内存方式通信的值类型结构体///</summary>publicstructServiceMsg{publicintId;publiclongNowTime;}internalclassProgram{privatestaticvoidMain(string[]args){Console.Write("请输入共享内存公用名(默认:testmap):");stringshareName=Console.ReadLine();if(string.IsNullOrEmpty(shareName))shareName="testmap";using(MemoryMappedFilemmf=MemoryMappedFile.CreateOrOpen(shareName,1024000,MemoryMappedFileAccess.ReadWrite)){boolmutexCreated;//进程间同步varmutex=newMutex(true,"testmapmutex",outmutexCreated);using(MemoryMappedViewStreamstream=mmf.CreateViewStream())//创建文件内存视图流{varwriter=newBinaryWriter(stream);for(inti=0;i<5;i++){writer.Write(i);Console.WriteLine("{0}位置写入流:{0}",i);}}mutex.ReleaseMutex();Console.WriteLine("启动状态服务,按【回车】读取共享内存数据");Console.ReadLine();mutex.WaitOne();using(MemoryMappedViewStreamstream=mmf.CreateViewStream()){varreader=newBinaryReader(stream);for(inti=0;i<10;i++){Console.WriteLine("{1}位置:{0}",reader.ReadInt32(),i);}}using(MemoryMappedViewAccessoraccessor=mmf.CreateViewAccessor(1024,10240)){intcolorSize=Marshal.SizeOf(typeof(ServiceMsg));ServiceMsgcolor;for(inti=0;i<50;i+=colorSize){accessor.Read(i,outcolor);Console.WriteLine("{1}\tNowTime:{0}",newDateTime(color.NowTime),color.Id);}}mutex.ReleaseMutex();}Console.WriteLine("测试:我是即时通讯-消息服务我启动啦!!!");Console.ReadKey();}}}
IMServer_State.exe代码
usingSystem;usingSystem.IO;usingSystem.IO.MemoryMappedFiles;usingSystem.Runtime.InteropServices;usingSystem.Threading;namespaceIMServer_State{///<summary>///用于共享内存方式通信的值类型结构体///</summary>publicstructServiceMsg{publicintId;publiclongNowTime;}internalclassProgram{privatestaticvoidMain(string[]args){Console.Write("请输入共享内存公用名(默认:testmap):");stringshareName=Console.ReadLine();if(string.IsNullOrEmpty(shareName))shareName="testmap";using(MemoryMappedFilemmf=MemoryMappedFile.CreateOrOpen(shareName,1024000,MemoryMappedFileAccess.ReadWrite)){Mutexmutex=Mutex.OpenExisting("testmapmutex");mutex.WaitOne();using(MemoryMappedViewStreamstream=mmf.CreateViewStream(20,0))//注意这里的偏移量{varwriter=newBinaryWriter(stream);for(inti=5;i<10;i++){writer.Write(i);Console.WriteLine("{0}位置写入流:{0}",i);}}using(MemoryMappedViewAccessoraccessor=mmf.CreateViewAccessor(1024,10240)){intcolorSize=Marshal.SizeOf(typeof(ServiceMsg));varcolor=newServiceMsg();for(inti=0;i<colorSize*5;i+=colorSize){color.Id=i;color.NowTime=DateTime.Now.Ticks;//accessor.Read(i,outcolor);accessor.Write(i,refcolor);Console.WriteLine("{1}\tNowTime:{0}",newDateTime(color.NowTime),color.Id);Thread.Sleep(1000);}}Thread.Sleep(5000);mutex.ReleaseMutex();}Console.WriteLine("测试:我是即时通讯-状态服务我启动啦!!!");Console.ReadKey();}}}
感谢各位的阅读,以上就是“C#.Net通信共享内存映射文件是什么”的内容了,经过本文的学习后,相信大家对C#.Net通信共享内存映射文件是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是主机评测网,小编将为大家推送更多相关知识点的文章,欢迎关注!
下一篇:误引用vuex-persistedstate导致用户信息无法清除怎么解决