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 (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();

    }

 C# .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();
        }
    }
文章来源地址https://www.toymoban.com/news/detail-739122.html

到了这里,关于C# .Net 多进程同步 通信 共享内存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux——进程通信之共享内存

    目录 一.  回顾上文 二.共享内存 1.定义 2.特点: 3.实现步骤: 如下为成功链接共享内存使用权的完整步骤: 4.函数介绍         4.1shmget函数         4.1.2参数介绍                4.2ftok函数:         4.2.1参数介绍                 关于ftok(); shmget();函数的

    2024年02月12日
    浏览(50)
  • (26)Linux 进程通信之共享内存(共享储存空间)

    共享内存是System V版本的最后一个进程间通信方式。 共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内

    2024年01月16日
    浏览(44)
  • Linux 共享内存mmap,进程通信

    进程间通信是操作系统中重要的概念之一,使得不同的进程可以相互交换数据和进行协作。其中,共享内存是一种高效的进程间通信机制,而内存映射(mmap)是实现共享内存的一种常见方法。 存储映射 I/O 是 一个磁盘文件 与 存储空间中的一个缓冲区相映射 。于是, 当从缓

    2024年02月13日
    浏览(42)
  • 【Linux】进程间通信——管道/共享内存

    进程间通信( Inter-Process Communication,简称IPC )是指不同进程之间进行数据交换和共享信息的机制和技术。在操作系统中,每个进程都是独立运行的,有自己的地址空间和数据,因此进程之间需要一种机制来进行通信,以便彼此协调工作、共享数据或者进行同步操作。 进程间

    2024年02月16日
    浏览(40)
  • 进程间通信--共享内存详解【Linux】

    本文详细讲解了共享内存的原理和使用,并且通过实例代码角度来深度理解共享内存,下面就让我们开始吧。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(

    2024年02月02日
    浏览(39)
  • 【Linux】进程间通信之共享内存

    共享内存比管道快哦~ 文章目录 前言 一、共享内存的实现原理 二、实现共享内存的代码 总结 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的

    2024年02月03日
    浏览(45)
  • C++ Windows进程间共享内存通信

    在项目工程中需要64位程序调用32位程序并加以通信。 实现了两个进程间的内存共享。 提示:以下是本篇文章正文内容,下面案例可供参考 1、进程间通信原理: 主要实现: • 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动

    2024年02月03日
    浏览(43)
  • Linux--进程间的通信-共享内存

    前文: Linux–进程间的通信-匿名管道 Linux–进程间的通信–进程池 Linux–进程间的通信-命名管道 对于两个进程,通过在内存开辟一块空间(操作系统开辟的),进程的虚拟地址通过页表映射到对应的共享内存空间中,进而实现通信 ; 特点和作用: 高效性: 共享内存是一种

    2024年04月26日
    浏览(38)
  • 【hello Linux】进程间通信——共享内存

    目录 前言: 1. System V共享内存 1. 共享内存的理解 2. 共享内存的使用步骤 3. 共享内存的使用         1. 共享内存的创建         查看共享内存         2. 共享内存的释放         3. 共享内存的挂接         4. 共享内存的去挂接 4. 共享内存的使用示例 1. 两进

    2024年02月01日
    浏览(91)
  • 【Linux】进程间的通信之共享内存

    利用 内存共享 进行进程间的通信的原理其实分为以下几个步骤: 在物理内存中创建一块共享内存。 将共享内存链接到要通信的进程的页表中,并通过页表进行进程地址空间的映射。 进程地址空间映射完毕以后返回首个虚拟地址,以便于进程之间进行通信。 根据共享内存的

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包