iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >.Net多进程通信共享内存映射文件Memory Mapped
  • 255
分享到

.Net多进程通信共享内存映射文件Memory Mapped

2024-04-02 19:04:59 255人浏览 薄情痞子
摘要

目录内存映射文件究竟是个什么?.net 共享内存 内存映射文件原理.Net 共享内存 演示代码.Net 进程间通信共享内存IMServer_Message.exe 代码IMServe

节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。

内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当。实际上,任何想要共享数据的通信模型都会在幕后使用它。

内存映射文件究竟是个什么?

内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作。物理存储是文件管理,而内存映射文件是操作系统级内存管理。

优势:

1.访问磁盘文件上的数据不需执行I/O操作和缓存操作(当访问文件数据时,作用尤其显著);

2.让运行在同一台机器上的多个进程共享数据(单机多进程间数据通信效率最高);

利用文件与内存空间之间的映射,应用程序(包括多个进程)可以通过直接在内存中进行读写来修改文件。.NET Framework 4 用托管代码按照本机windows函数访问内存映射文件的方式来访问内存映射文件,管理 Win32 中的内存映射文件。

有两种类型的内存映射文件:

  • 持久内存映射文件

持久文件是与磁盘上的源文件关联的内存映射文件。在最后一个进程使用完此文件后,数据将保存到磁盘上的源文件中。这些内存映射文件适合用来处理非常大的源文件。

  • 非持久内存映射文件

非持久文件是未与磁盘上的源文件关联的内存映射文件。当最后一个进程使用完此文件后,数据将丢失,并且垃圾回收功能将回收此文件。这些文件适用于为进程间通信(IPC) 创建共享内存。

1)在多个进程之间进行共享(进程可通过使用由创建同一内存映射文件的进程所指派的公用名来映射到此文件)。

2)若要使用一个内存映射文件,则必须创建该内存映射文件的完整视图或部分视图。还可以创建内存映射文件的同一部分的多个视图,进而创建并发内存。为了使两个视图能够并发,必须基于同一内存映射文件创建这两个视图。

3)如果文件大于应用程序用于内存映射的逻辑内存空间(在 32 位计算机上为2GB),则还需要使用多个视图。

有两种类型的视图:流访问视图和随机访问视图。使用流访问视图可对文件进行顺序访问;在使用持久文件时,随机访问视图是首选方法。

.Net 共享内存 内存映射文件原理

通过操作系统的内存管理器访问的,因此会自动将此文件分隔为多个页,并根据需要对其进行访问。您不需要自行处理内存管理。如下图:

.Net 共享内存 演示代码

   //持久内存映射文件:基于现有文件创建一个具有指定公用名的内存映射文件
    using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\内存映射文件.data", FileMode.Open, "公用名"))
    {
        //通过指定的 偏移量和大小 创建内存映射文件视图服务器
        using (var accessor = mmf.CreateViewAccessor(offset, length)) //偏移量,可以控制数据存储的内存位置;大小,用来控制存储所占用的空间
        {
            //Marshal提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。
            int size = Marshal.SizeOf(typeof(char));
            //修改内存映射文件视图
            for (long i = 0; i < length; i += size)
            {
                char c= accessor.ReadChar(i);
                accessor.Write(i, ref c);
            }
        }
    }
    //另一个进程或线程可以,在系统内存中打开一个具有指定名称的现有内存映射文件
    using (var mmf = MemoryMappedFile.OpenExisting("公用名"))
    {
        using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))
        {
            int size = Marshal.SizeOf(typeof(char));
            for (long i = 0; i < length; i += size)
            {
                char c = accessor.ReadChar(i);
                accessor.Write(i, ref c);
            }
        }
    }
//非持久内存映射文件:未映射到磁盘上的现有文件的内存映射文件
    using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))
    {
        bool mutexCreated;
        //进程间同步
        Mutex mutex = newMutex(true, "testmapmutex", out mutexCreated);
        using (var stream = mmf.CreateViewStream()) //创建文件内存视图流 基于流的操作
        {
            var writer = newBinaryWriter(stream);
            writer.Write(1);
        }
        mutex.ReleaseMutex();
        Console.WriteLine("Start Process B and press ENTER to continue.");
        Console.ReadLine();
        mutex.WaitOne();
        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
        {
            var reader = newBinaryReader(stream);
            Console.WriteLine("Process A says: {0}", reader.ReadBoolean());
            Console.WriteLine("Process B says: {0}", reader.ReadBoolean());
        }
        mutex.ReleaseMutex();
    }
    using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
    {
         Mutex mutex = Mutex.OpenExisting("testmapmutex");
        mutex.WaitOne();
       using (var stream = mmf.CreateViewStream(1, 0))//注意这里的偏移量
        {
            var writer = newBinaryWriter(stream);
            writer.Write(0);
        }
        mutex.ReleaseMutex();
    }

.Net 进程间通信共享内存

完整示例:C#共享内存非持久化方式通讯的例子,通讯时的线程和进程控制也没有问题。

  • 先启动消息服务IMServer_Message,
  • 再启动状态服务IMServer_State,
  • IMServer_Message回车一次(创建共享内存公用名和公用线程,并视图流方式写共享内存),
  • IMServer_State回车一次(获取共享内存并视图流方式写、视图访问器写入结构体类型)
  • 并立刻IMServer_Message再回车一次(读取刚刚写入的信息),
  • 观察IMServer_State屏显变化并等待(线程锁)约5s(线程锁被释放)后
  • 在IMServer_Message上观察屏显(显示刚刚写入共享内存的信息)

IMServer_Message.exe 代码

using System;
using System.io;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Threading;
namespace IMServer_Message
{
    /// <summary>
    /// 用于共享内存方式通信的 值类型 结构体
    /// </summary>
    public struct ServiceMsg
    {
        public int Id;
        public long NowTime;
    }
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.Write("请输入共享内存公用名(默认:testmap):");
            string shareName = Console.ReadLine();
            if (string.IsNullOrEmpty(shareName))
                shareName = "testmap";
            using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(shareName, 1024000,MemoryMappedFileAccess.ReadWrite))
            {
                bool mutexCreated;
                //进程间同步
                var mutex = new Mutex(true, "testmapmutex", out mutexCreated);
                using (MemoryMappedViewStream stream = mmf.CreateViewStream()) //创建文件内存视图流
                {
                    var writer = new BinaryWriter(stream);
                    for (int i = 0; i < 5; i++)
                    {
                        writer.Write(i);
                        Console.WriteLine("{0}位置写入流:{0}", i);
                    }
                }
                mutex.ReleaseMutex();
                Console.WriteLine("启动状态服务,按【回车】读取共享内存数据");
                Console.ReadLine();
                mutex.WaitOne();
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    var reader = new BinaryReader(stream);
                    for (int i = 0; i < 10; i++)
                    {
                        Console.WriteLine("{1}位置:{0}", reader.ReadInt32(), i);
                    }
                }
                using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(1024, 10240))
                {
                    int colorSize = Marshal.SizeOf(typeof (ServiceMsg));
                    ServiceMsg color;
                    for (int i = 0; i < 50; i += colorSize)
                    {
                        accessor.Read(i, out color);
                        Console.WriteLine("{1}\tNowTime:{0}", new DateTime(color.NowTime), color.Id);
                    }
                }
                mutex.ReleaseMutex();
            }
            Console.WriteLine("测试: 我是 即时通讯 - 消息服务 我启动啦!!!");
            Console.ReadKey();
        }
    }
}

IMServer_State.exe代码

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Threading;
namespace IMServer_State
{
    /// <summary>
    /// 用于共享内存方式通信的 值类型 结构体
    /// </summary>
    public struct ServiceMsg
    {
        public int Id;
        public long NowTime;
    }
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.Write("请输入共享内存公用名(默认:testmap):");
            string shareName = Console.ReadLine();
            if (string.IsNullOrEmpty(shareName))
                shareName = "testmap";
            using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(shareName, 1024000,MemoryMappedFileAccess.ReadWrite))
            {
                Mutex mutex = Mutex.OpenExisting("testmapmutex");
                mutex.WaitOne();
                using (MemoryMappedViewStream stream = mmf.CreateViewStream(20, 0)) //注意这里的偏移量
                {
                    var writer = new BinaryWriter(stream);
                    for (int i = 5; i < 10; i++)
                    {
                        writer.Write(i);
                        Console.WriteLine("{0}位置写入流:{0}", i);
                    }
                }
                using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(1024, 10240))
                {
                    int colorSize = Marshal.SizeOf(typeof (ServiceMsg));
                    var color = new ServiceMsg();
                    for (int i = 0; i < colorSize*5; i += colorSize)
                    {
                        color.Id = i;
                        color.NowTime = DateTime.Now.Ticks;
                        //accessor.Read(i, out color);
                        accessor.Write(i, ref color);
                        Console.WriteLine("{1}\tNowTime:{0}", new DateTime(color.NowTime), color.Id);
                        Thread.Sleep(1000);
                    }
                }
                Thread.Sleep(5000);
                mutex.ReleaseMutex();
            }
            Console.WriteLine("测试: 我是 即时通讯 - 状态服务 我启动啦!!!");
            Console.ReadKey();
        }
    }
}

以上就是.Net多进程通信共享内存映射文件Memory Mapped的详细内容,更多关于.Net多进程通信共享内存映射的资料请关注编程网其它相关文章!

--结束END--

本文标题: .Net多进程通信共享内存映射文件Memory Mapped

本文链接: https://www.lsjlt.com/news/147740.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • .Net多进程通信共享内存映射文件Memory Mapped
    目录内存映射文件究竟是个什么?.Net 共享内存 内存映射文件原理.Net 共享内存 演示代码.Net 进程间通信共享内存IMServer_Message.exe 代码IMServe...
    99+
    2024-04-02
  • C#.Net通信共享内存映射文件是什么
    这篇文章主要讲解了“C#.Net通信共享内存映射文件是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#.Net通信共享内存映射文件是什么”吧!节点通信存在两种模型:共享内存(Share...
    99+
    2023-06-30
  • 怎么在c#中通过内存映射共享文件
    本篇文章给大家分享的是有关怎么在c#中通过内存映射共享文件,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。App1代码:using System;using ...
    99+
    2023-06-14
  • c# 通过内存映射实现文件共享内存的示例代码
    目录App1代码:App2代码:App3代码:内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,比如使用c语言的 mem...
    99+
    2024-04-02
  • Python进程间通信之共享内存
    前一篇博客说了怎样通过命名管道实现进程间通信,但是要在windows是使用命名管道,需要使用python调研windows api,太麻烦,于是想到是不是可以通过共享内存的方式来实现。查了一下,Python中可以使用mmap模块来...
    99+
    2023-01-31
    进程 内存 通信
  • php进程通信之共享内存详细讲解
    目录常见进程通信方式system V共享内存php使用共享内存共享内存基本函数使用父子进程通信配合信号量使用非血缘关系进程共享内存通信共享内存的特性常见进程通信方式 system ...
    99+
    2024-04-02
  • Linux之进程间通信(共享内存【mmap实现+系统V】)
    目录共享内存mmap()及其相关的系统调用mmap()munmap()共享内存的使用命令管理共享内存总结共享内存 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式,两个不同的进程A、B共享内存的意思就是:同一...
    99+
    2023-03-23
    Linux进程间通信 Linux共享内存 Linux进程
  • node中怎么利用进程通信实现Cluster共享内存
    node中怎么利用进程通信实现Cluster共享内存,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。##IPC的基本用法:// w...
    99+
    2024-04-02
  • C++中怎么用共享文件实现进程间通信
    在C++中使用共享文件实现进程间通信,可以通过以下步骤实现: 创建一个共享文件,可以使用open()函数或者fopen()函数创建...
    99+
    2024-04-02
  • 管道、套接字和共享内存:进程通信的秘密武器
    管道 管道是一种半双工通信机制,它允许两个相关进程在同一主机上进行通信。管道创建时,会建立一个缓冲区,用于存储进程之间交换的数据。写入进程将数据写入缓冲区,而读取进程从缓冲区中读取数据。管道具有以下特点: 专用且高效,仅限于相关进程使用...
    99+
    2024-04-02
  • 如何解决linux使用共享内存通信的进程同步退出问题
    本篇内容主要讲解“如何解决linux使用共享内存通信的进程同步退出问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何解决linux使用共享内存通信的进程同步退出问题”吧!两个甚至多个进程使用...
    99+
    2023-06-13
  • 【Linux】进程间通信(万字详解)—— 匿名管道 | 命名管道 | System V | 共享内存
    🌈欢迎来到Linux专栏~~进程通信 ...
    99+
    2023-08-22
    linux 服务器 unix
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作