多进程架构关键技术之FileMapping技术应用

news2024/9/22 3:36:37

在这里插入图片描述

1. 前言

在多进程架构设计中,使用FileMapping技术是一种关键的技术选择。它能够显著提升多进程间数据共享和通信的效率,同时简化了复杂的进程间数据交互和同步管理。以下是FileMapping技术在多进程架构设计中的应用及其关键优势:
在这里插入图片描述

2. 共享数据存储

FileMapping技术允许多个进程将同一个文件的部分或全部内容映射到它们各自的虚拟地址空间中。这意味着多个进程可以直接访问和操作共享的数据,而无需通过传统的IPC机制(如管道或消息队列)来传递数据。这种直接的共享方式极大地简化了进程间的通信和数据同步。

3. 高效的数据访问

通过FileMapping技术,进程可以像访问内存一样高效地读取和写入共享文件的数据。操作系统负责将文件的内容按需加载到内存中,并根据进程的访问模式进行优化。相比于传统的文件I/O操作,这种直接的内存访问方式显著提升了数据的访问速度和响应性能。

4. 数据一致性和同步

在多进程应用中,保证共享数据的一致性和安全性至关重要。FileMapping技术结合了操作系统提供的同步原语(如互斥体和信号量),可以有效地管理多个进程对共享数据的访问。通过适当的同步机制,可以避免竞态条件和数据不一致的问题,确保系统的稳定性和可靠性。

5. 适用场景

FileMapping技术特别适合于以下场景的多进程架构设计:

  • 数据库系统:多个进程需要同时访问和更新数据库文件。
  • 图像处理应用:多个进程需要并行处理大型图像数据。
  • 实时数据处理:需要高效共享和更新实时数据的应用程序。

6. 异常处理和性能优化

在使用FileMapping技术时,开发者需要考虑到操作系统和硬件层面的异常情况,如文件访问错误或内存映射失败。合理的异常处理和资源管理能够提升系统的稳定性和可靠性。此外,优化文件映射的大小和使用方式可以进一步提升系统的性能和响应速度。

7.示例应用

实现多进程架构,通过FileMapping技术实现跨进程通信,并构建一个缓存库,让实体User在不同进程之间共享数据。

7.1创建一个共享的缓存库

首先,我们需要创建一个共享的缓存库,这个库负责管理和维护用户数据,允许多个进程访问和修改数据。
新增User实体类:

using System.ComponentModel.DataAnnotations;

namespace FileMappingCache
{
    public class User
    {
        public int Id { get; set; }
        [MaxLength(100)]
        public string Name { get; set; }
    }
}

新增 FMCache共享缓存类:

using System.Runtime.InteropServices;
using System.Text;

namespace FileMappingCache
{
    public static class FMCache
    {
        private const int MaxUsers = 1000;
        private const string MapName = "UserCacheMap";
        private const int UserSize = 104; // Assume each User takes up 104 bytes (4 bytes for Id + 100 bytes for Name)

        [DllImport("kernel32", SetLastError = true)]
        private static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);

        [DllImport("kernel32", SetLastError = true)]
        private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);

        [DllImport("kernel32", SetLastError = true)]
        private static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

        [DllImport("kernel32", SetLastError = true)]
        private static extern bool CloseHandle(IntPtr hObject);

        private static IntPtr _hMapFile = IntPtr.Zero;
        private static IntPtr _pBaseAddress = IntPtr.Zero;

        public static void Initialize()
        {
            _hMapFile = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, MaxUsers * UserSize, MapName);

            if (_hMapFile == IntPtr.Zero)
            {
                throw new Exception("Unable to create file mapping.");
            }

            _pBaseAddress = MapViewOfFile(_hMapFile, 0xF001F, 0, 0, MaxUsers * UserSize);

            if (_pBaseAddress == IntPtr.Zero)
            {
                throw new Exception("Unable to map view of file.");
            }
        }

        public static void AddUser(User user)
        {
            int offset = user.Id * UserSize;
            byte[] buffer = new byte[UserSize];

            BitConverter.GetBytes(user.Id).CopyTo(buffer, 0);
            Encoding.UTF8.GetBytes(user.Name.PadRight(100)).CopyTo(buffer, 4);

            Marshal.Copy(buffer, 0, IntPtr.Add(_pBaseAddress, offset), UserSize);
        }

        public static void RemoveUser(int id)
        {
            int offset = id * UserSize;
            byte[] buffer = new byte[UserSize];

            Marshal.Copy(buffer, 0, IntPtr.Add(_pBaseAddress, offset), UserSize);
        }

        public static User GetUserById(int id)
        {
            int offset = id * UserSize;
            byte[] buffer = new byte[UserSize];

            Marshal.Copy(IntPtr.Add(_pBaseAddress, offset), buffer, 0, UserSize);

            int userId = BitConverter.ToInt32(buffer, 0);
            string userName = Encoding.UTF8.GetString(buffer, 4, 100).TrimEnd('\0');

            if (userId == 0)
            {
                return null;
            }

            return new User { Id = userId, Name = userName };
        }
        public static User[] GetAllUsers()
        {
            User[] users = new User[MaxUsers];
            for (int i = 0; i < MaxUsers; i++)
            {
                users[i] = GetUserById(i);
            }
            return users;
        }
        public static User GetUserWithMaxId()
        {
            User maxUser = null;
            for (int i = 0; i < MaxUsers; i++)
            {
                User user = GetUserById(i);
                if (user != null)
                {
                    if (maxUser == null || user.Id > maxUser.Id)
                    {
                        maxUser = user;
                    }
                }
            }
            return maxUser;
        }

        public static int GetUserCount()
        {
            int count = 0;
            for (int i = 0; i < MaxUsers; i++)
            {
                if (GetUserById(i) != null)
                {
                    count++;
                }
            }
            return count;
        }

        public static void UpdateUser(User user)
        {
            int offset = user.Id * UserSize;
            byte[] buffer = new byte[UserSize];

            BitConverter.GetBytes(user.Id).CopyTo(buffer, 0);
            Encoding.UTF8.GetBytes(user.Name.PadRight(100)).CopyTo(buffer, 4);

            Marshal.Copy(buffer, 0, IntPtr.Add(_pBaseAddress, offset), UserSize);
        }

        public static void Cleanup()
        {
            if (_pBaseAddress != IntPtr.Zero)
            {
                UnmapViewOfFile(_pBaseAddress);
                _pBaseAddress = IntPtr.Zero;
            }

            if (_hMapFile != IntPtr.Zero)
            {
                CloseHandle(_hMapFile);
                _hMapFile = IntPtr.Zero;
            }
        }
    }

}

新增UserCache类,封装对FMCache的调用:

namespace FileMappingCache
{
    public class UserCache
    {
        static UserCache()
        {
            FMCache.Initialize();
        }

        public static void QueryDataList()
        {
            for (int i = 0; i < 1000; i++)
            {
                var user = FMCache.GetUserById(i);
                if (user != null)
                {
                    Console.WriteLine($"ID: {user.Id}, Name: {user.Name}");
                }
            }
        }
        public static User GetUserById(int id)
        {
            return FMCache.GetUserById(id);
        }

        public static void AddNewUser(User user)
        {
            FMCache.AddUser(user);
        }

        public static void RemoveUser(int id)
        {
            FMCache.RemoveUser(id);
        }

        public static void Cleanup()
        {
            FMCache.Cleanup();
        }

        public static int GetUserCount()
        {
            return FMCache.GetUserCount();
        }

    }
}

7.2 新增Server控制台程序

展示已经添加的用户数量

using FileMappingCache;

namespace Server
{
    internal class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                var count = UserCache.GetUserCount();
                Console.WriteLine("已添加用户数量:" + count);
                Thread.Sleep(1000);
            }
        }
    }
}

7.3 新增Client控制台程序

定时向缓存中添加User数据

using FileMappingCache;

namespace Client
{
    internal class Program
    {

        static void Main(string[] args)
        {
            int index = 1;
            while (true)
            {
                index++;
                UserCache.AddNewUser(new User { Id = index, Name = "Alice_" + index });
                var user = UserCache.GetUserById(index);
                Console.WriteLine($"{user.Id},{user.Name}");
                Thread.Sleep(1000);
            }
        }
    }
}

7.4 执行结果

配置程序启动的先后顺序
在这里插入图片描述
执行观察结果,实现数据跨进程访问。
在这里插入图片描述

7.5 小结

通过上述实现,可以在C#中构建一个基本的多进程架构系统,通过FileMapping技术实现跨进程通信,并允许不同进程之间共享和操作用户数据,这是一个简单的实现,需要注意的是,确保多个进程之间对共享资源的访问是安全的,避免竞争条件和数据损坏,共享内存中存储和读取数据时,需要精确计算和管理数据的位置,确保数据的完整性和正确性。

8、总结

FileMapping技术在多进程架构设计中是一项强大的工具,可以有效地提升系统的性能和并发能力,特别适用于需要高效数据共享和通信的应用场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1997263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux项目自动构建工具 make/makefile

目录 0.前言 1.make/makefile是什么 2.makefile的语法 2.1基本语法 2.2依赖关系 2.3. 示例&#xff1a;一个简单的C程序 3.使用指令自动构建与清除 3.1自动构建 3.2自动清除 3.3自动化工作流 3.4扩展&#xff1a;更多伪目标 4.make的工作原理 5.使用make/makefile的优势 6.小结…

高质量WordPress下载站模板5play主题源码

5play下载站是由国外站长开发的一款WordPress主题&#xff0c;主题简约大方&#xff0c;为v1.8版本&#xff0c; 该主题模板中包含了上千个应用&#xff0c;登录后台以后只需要简单的三个步骤就可以轻松发布apk文章&#xff0c; 我们只需要在WordPress后台中导入该主题就可以…

Spring配置

1.Spring的两大核心思想IOC和AOP思想 1.1类注解 1.Controller, Service, Configuration, Component, Repository 1.2方法注解 bean&#xff08;这个方法搭配上面的五大注解进行使用&#xff09; 2.Bean的名称 2.1.类注解名称 &#xff08;1&#xff09;默认首字母小写驼…

数组结构:链式结构二叉树

1.实现链式结构二叉树 用链表来表示一棵二叉树&#xff0c;即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成&#xff0c;数据域和左右指针域&#xff0c;左右指针分别用来给结点的左孩子和右孩子所在的链结点的存储地址&#xff0c;其结构如下&#xff1…

Micrometer Tracing和Zipkin实现链路追踪

一、为什么使用链路追踪 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个…

【经验分享】ShardingSphere+Springboot-03 : COMPLEX_INLINE 复杂行表达式分片算法

文章目录 3.3 复杂分片算法3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 3.3 复杂分片算法 3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 复合分片比较灵活&#xff0c;适合于分片的字段比较多&#xff0c;分片比较复杂的场景&#xff0c;使用这种分片的话必须对自己的业务比较…

深度学习——神经网络(neural network)详解(二). 带手算步骤,步骤清晰0基础可看

深度学习——神经网络&#xff08;neural network&#xff09;详解&#xff08;二&#xff09;. 手算步骤&#xff0c;步骤清晰0基础可看 前文如下&#xff1a;深度学习——神经网络&#xff08;neural network&#xff09;详解&#xff08;一&#xff09;. 带手算步骤&#x…

Java面试篇(JVM相关专题)

文章目录 0. 前言1. 为什么要学 JVM2. 什么是 JVM3. JVM 的好处3.1 一次编写&#xff0c;到处运行3.2 自动内存管理&#xff08;基于垃圾回收机制&#xff09; 4. 要学习哪些 JVM 的哪些内容5. JVM 的组成5.1 程序计数器5.2 堆5.3 什么是虚拟机栈常见问题一&#xff1a;垃圾回收…

代码+视频,R语言VRPM绘制多种模型的彩色列线图

列线图&#xff0c;又称诺莫图&#xff08;Nomogram&#xff09;&#xff0c;它是建立在回归分析的基础上&#xff0c;使用多个临床指标或者生物属性&#xff0c;然后采用带有分数高低的线段&#xff0c;从而达到设置的目的&#xff1a;基于多个变量的值预测一定的临床结局或者…

机器学习入门篇之监督学习(回归篇)——多元线性回归的原理介绍

在机器学习入门之监督学习&#xff08;分类篇&#xff09;-CSDN博客&#xff0c;以及初步接触了机器学习&#xff0c;在这片文章中我们继续沿着思维导图学习监督学习的剩下部分&#xff0c;回归。 在监督学习中&#xff0c;回归是一种预测型建模技术&#xff0c;它涉及预测一个…

尚硅谷谷粒商城项目笔记——十、调试前端项目renren-fast-vue【电脑CPU:AMD】

十、调试前端项目renren-fast-vue 如果遇到其他问题发在评论区&#xff0c;我看到后解决 1 先下载安装git git官网下载地址 2 登录gitee搜索人人开源找到renren-fast-vue复制下载链接。【网课视频中也有详细步骤】 3 下载完成后桌面会出现renren-fast-vue的文件夹 4 开始调…

【阿旭机器学习实战】【39】脑肿瘤数据分析与预测案例:数据分析、预处理、模型训练预测、评估

《------往期经典推荐------》 一、【100个深度学习实战项目】【链接】&#xff0c;持续更新~~ 二、机器学习实战专栏【链接】&#xff0c;已更新31期&#xff0c;欢迎关注&#xff0c;持续更新中~~ 三、深度学习【Pytorch】专栏【链接】 四、【Stable Diffusion绘画系列】专…

python如何判断中文是否一致

Python判断两个相等的中文字符串为false&#xff0c;将两个待比较的字符串都把unicode编码设为‘utf-8’也不能解决问题&#xff0c;具体原因如下&#xff1a; 1、首先查看待比较两个字符串的编码格式 &#xff0c;使用命令&#xff1a; import chardet ...... string_code c…

macos重装系统 启动U盘制作方法 - createinstallmedia 命令使用方法总结

macos重装系统比windows要稍微复杂一些&#xff0c;不过还好&#xff0c;macos系统安装app这个Apple官方提供的系统软件里面默认就内置了一个可用为我们制作启动盘的工具 createinstallmedia 我们下载的apple安装镜像要门是 dmg/pkg/iso 的压缩档案格式的&#xff0c;要么是 x…

智慧安监管理平台建设方案

1. 前言&#xff1a;智慧安监云平台概述 "互联网"安全生产监管监测大数据平台&#xff0c;利用移动互联网、物联网、云计算等技术&#xff0c;实现安全生产监管业务的智能化处理和统一集中管理。平台旨在构建服务导向的智慧安监管理平台&#xff0c;推动安全生产信息…

React 后台管理项目 入门项目 简洁清晰保姆级内容讲解

序章 React Hook的后台管理项目&#xff0c;从0到1搭建&#xff0c;内容非常丰富涵盖项目搭建、路由配置、用户鉴权、首页报表、用户列表、前后端联调等功能&#xff0c;推荐指数&#xff1a;5颗星&#xff01; 视频学习链接: React 通用后台管理-零基础从0到1详细的入门保姆…

PHYS_OPT_SKIPPED

当跳过候选基元单元的物理优化时 单元格的PHYS_OPT_MODIFIED属性已更新&#xff0c;以反映跳过的优化。 当对同一单元格跳过多个优化时&#xff0c;OPT_skipped值包含 跳过的优化列表。 架构支持 所有架构。 适用对象 PHYS_OPT_SKIPPED属性放置在单元格上。 价值观 下表列出了各…

【Qt】动态加载DLL之QLibrary类学习(内含完整Demo源码)

各位看官这里是目录↓↓↓&#xff0c;点击直达哦~ 前言一、QLibrary简介二、常用方法2.1 构造函数2.2 设置要访问的动态库——setFileName()2.3 加载动态库——load()2.4 获取动态库的名字——fileName()2.5 解析共享库中的符号——resolve() 三、示例&#xff08;Demo&#x…

入门学习使用overleaf和latex

文章目录 1.下载对应的latex论文模板2.overleaf平台的使用2.1overleaf平台的介绍2.2overleaf平台模板文件的上传2.3latex语法的学习2.3.2 分段(如下图显示)2.3.3 其他2.3.4简单latex实操2.3.5 换行符和换页符2.3.6左右居中对齐2.3.7 字体设置2.3.8插入固定位置图片2.3.9文字包围…

KillWxapkg 自动化反编译微信小程序,小程序安全评估工具,发现小程序安全问题,自动解密,解包,可还原工程目录,支持修改Hook,小程序

纯Golang实现&#xff0c;一个用于自动化反编译微信小程序的工具&#xff0c;小程序安全利器&#xff0c;自动解密&#xff0c;解包&#xff0c;可还原工程目录&#xff0c;支持微信开发者工具运行 由于采用了UPX压缩的软件体积&#xff0c;工具运行时可能会出现错误报告&…