2.3 主程序和外部IO交互 (文件映射方式)----IO Server实现

2.3 主程序和外部IO交互 (文件映射方式)----IO Server C++实现

效果显示

在这里插入图片描述

1 内存共享概念

基本原理:以页面为单位,将一个普通文件映射到内存中,达到共享内存和节约内存的目的,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能
windows和linux都提供了原生的系统级的C++接口,可以将文件映射到内存

优点: 32位|64位 客户端都可以同时连接到Server上

1 参考资料 探索内存原理的内存映射文件(图文详解)

2 IO交互工作示意图

1 必须先打开IO Server 创建内存映射,然后打开IO Client才有效
2 IO Client 可以32位也可以64位
IO 交互示意图

3 C++ 代码实现

3.1 shareddataServer.h 头文件中引用

尽量做到Windows |Linux 下都能够通用

 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
 #define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
	#include <windows.h>
#elif defined(linux) || defined(__linux)
	#include <string.h>
	#include <sys/mman.h>
	#include <fcntl.h>
	#include <unistd.h> 
#endif 
3.2 shareddataServer.h 主要调用接口

在后面的测试中,我们主要演示DM8 来作为IO的 输入和输出

3.2.1 预定义变量名称,为了能够Linux|Windows下通用
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)   

#elif defined(linux) || defined(__linux)
   typedef void *HANDLE;
   typedef void *LPVOID;
   typedef long long __int64;
    typedef __int64 LONG_PTR, *PLONG_PTR;
     typedef unsigned long long ULONG_PTR;
    typedef unsigned long long  *PULONG_PTR; 
    typedef int BOOL; 
   #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
#endif
3.2.2 接口定义

BD_API  int  GetIOData(uchar* p_IOData, int start, int len);
BD_API  int  SetIOData(uchar* p_IOData, int start, int len);
BD_API  int  SetDM8(uchar* p_DM8, int start, int len);
BD_API  int  GetDM8(uchar* p_DM8, int start, int len);
BD_API  int  GetDM16(uchar* p_DM16, int start, int len);
BD_API  int  SetDM16(uchar* p_DM16, int start, int len); 


/**
 * ***********************************************************************************************
 * @brief ReleaseMMF
 * 销毁资源
 * 
 * @return BD_API 
 * ***********************************************************************************************
 */
BD_API void ReleaseMMF();
/**
 * ***********************************************************************************************
 * @brief 
 * 
 * 
 * @return BD_API 
 * ***********************************************************************************************
 */
BD_API int Create_Server();
3.3 shareddataServer.cpp 接口实现
3.3.0 MMF 句柄定义
namespace SHAREDDATA
{ 
    #pragma region MMF 内存共享 IO 区
    // 创建共享文件句柄 
    HANDLE hMapFile_IO = INVALID_HANDLE_VALUE;
     // 文档句柄
    int  fd_io=-1;
    #pragma endregion MMF 内存IO 区
    #pragma region MMF 内存共享 DM8 区
    // 创建共享文件句柄 
    HANDLE hMapFile_DM8 = INVALID_HANDLE_VALUE;
    // 文档句柄
    int  fd_dm8=-1;
    #pragma endregion MMF 内存DM8 区
    #pragma region MMF 内存共享 DM16 区
    // 创建共享文件句柄 
    HANDLE hMapFile_DM16 = INVALID_HANDLE_VALUE;
   // 文档句柄
    int  fd_dm16=-1;
    #pragma endregion MMF 内存DM16 区
} 
                        
3.3.1 Create_Server()
namespace SHAREDDATA
{ 
/**
 * ***********************************************************************************************
 * @brief 
 * Create_Server
 * 创建一个server
 * 
 * @return BD_API 
 * ***********************************************************************************************
 */
  BD_API int  Create_Server()
{
	int nRet = 0; 
	try
	{ 	
        #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
        // &0 DMIO
		hMapFile_IO = CreateFileMapping(
			INVALID_HANDLE_VALUE,   // 物理文件句柄
			NULL,   // 默认安全级别
			PAGE_READWRITE,   // 可读可写
			0,   // 高位文件大小
			n_max_IO_uchars,   // 低位文件大小
			"ShareMemoryIO"   // 共享内存名称
		);
		if (hMapFile_IO != INVALID_HANDLE_VALUE&&   hMapFile_IO > 0)nRet = 0;
		else return   -1;
		// &1 DM8
		hMapFile_DM8 = CreateFileMapping(
			INVALID_HANDLE_VALUE,   // 物理文件句柄
			NULL,   // 默认安全级别
			PAGE_READWRITE,   // 可读可写
			0,   // 高位文件大小
			n_max_DM8s,   // 低位文件大小
			"ShareMemoryDM8"   // 共享内存名称  
		);
		if (hMapFile_DM8 != INVALID_HANDLE_VALUE && hMapFile_DM8 > 0)nRet = 0;
		else return   -1;
		// &2 DM16
		hMapFile_DM16 = CreateFileMapping(
			INVALID_HANDLE_VALUE,   // 物理文件句柄
			NULL,   // 默认安全级别
			PAGE_READWRITE,   // 可读可写
			0,   // 高位文件大小
			n_max_DM16s,   // 低位文件大小
			"ShareMemoryDM16"   // 共享内存名称
		); 
 
 #elif defined(linux) || defined(__linux)
        // specify shared file path
	 // 路径一定要存在,否则会报警
       // &0 DMIO
	 string  shared_file_io = path+"ShareMemoryIO";
     fd_io = open(shared_file_io.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
	 if (fd_io < 0)
		{cout << "create file error" << endl;return -1;
        }
        ftruncate(fd_io, n_max_IO_uchars); // extend file size
     // map memory to file
	 //hMapFile_IO = mmap(NULL, 			n_max_IO_uchars,    , PROT_READ | PROT_WRITE, MAP_SHARED, fd_io, 0);     
            // &0 DM8
	 string shared_file_dm8 = path+"ShareMemoryDM8";
     fd_dm8 = open(shared_file_dm8.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
	 if (fd_dm8 < 0)
		{cout << "create file error" << endl;return -1;
        }
         ftruncate(fd_dm8, n_max_DM8s); // extend file size
     // map memory to file
	//hMapFile_DM8 = mmap(NULL, n_max_DM8s,    , PROT_READ | PROT_WRITE, MAP_SHARED, fd_dm8, 0);
      // &0 DM16
	 string shared_file_dm16= path+"ShareMemoryDM16";
     fd_dm16 = open(shared_file_dm8.c_str(), O_CREAT | O_RDWR | O_TRUNC, 00777);
	 if (fd_dm16 < 0)
		{cout << "create file error" << endl;return -1;
        }
     ftruncate(fd_dm16, n_max_DM16s); // extend file size  
 #endif
	}
	catch (exception& e)
	{
		nRet = -1;
	}
	return nRet;
}
#pragma region  销毁共享文件 句柄
// 销毁内存 MMF 句柄
BD_API void ReleaseMMF()
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)  
	if (hMapFile_IO != NULL)CloseHandle(hMapFile_IO);
	if (hMapFile_DM8 != NULL)CloseHandle(hMapFile_DM8);
	if (hMapFile_DM16 != NULL)CloseHandle(hMapFile_DM16); 
#elif defined(linux) || defined(__linux)

    if(fd_io>=0)close(fd_io);
    if(fd_dm8>=0)close(fd_dm8);
    if(fd_dm16>=0)close(fd_dm16);
      
#endif
} 
#pragma endregion  
}

3.3.2 重新定义MapViewofFile_New| UnMapViewofFile_New
 LPVOID  MapViewofFile_New(HANDLE handle,const int& fd, const int& size) 
  {
    LPVOID lpBase=nullptr;
    if(handle==nullptr||size==0)return lpBase;
    #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)   

			// 映射缓存区视图 , 得到指向共享内存的指针
			  lpBase = MapViewOfFile(
				handle,            // 共享内存的句柄
				FILE_MAP_ALL_ACCESS, // 可读写许可
				0,
				0,
				size
			);
     #elif defined(linux) || defined(__linux)
        if(fd<0)return nullptr;
        	// map memory to file
     	lpBase = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     #endif

     return lpBase;
  }

  void  UnMapViewofFile_New(HANDLE handle,const int& size)
  {
   if(handle==nullptr||size==0)return ;
    #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)   

		 	// 解除文件映射
			UnmapViewOfFile(handle);
     #elif defined(linux) || defined(__linux)
        	// unmap and close
	    munmap(handle, size);
     #endif
     
     return;
  }

3.3.3 SetDM8|GetDM8 函数接口实现
   /// @brief SetDM8
    /// @param p_DM8 
    /// @param start 
    /// @param len 
    /// @return 
    BD_API  int  SetDM8(uchar* p_DM8, int start, int len)
    {
        int nRet = 0;
        std::lock_guard<std::mutex> lock(_mutex);
        try
        {
            if (start > n_max_DM8s)
            {
                len = 0;
                nRet = -1;
                return nRet;
            }
            if (len + start > n_max_DM8s)
            {
                len = n_max_DM8s - start;
            }
            //  len 一定》0
            if (len > 0)
            {          
                // 映射缓存区视图 , 得到指向共享内存的指针
                LPVOID lpBase = MapViewofFile_New(hMapFile_DM8,fd_dm8,  n_max_DM8s);  
                memcpy((uchar*)lpBase + start, p_DM8, len);
                //memcpy(DM_8 + start, p_DM8, len);
                // 解除文件映射  
                UnMapViewofFile_New(lpBase, n_max_DM8s);
            }
            else nRet = -1;
        }
        catch (exception& e)
        {
            nRet = -1;
        }
        return nRet;
    }

    BD_API  int  GetDM8(uchar* p_DM8, int start, int len)
    {
        int nRet = 0;
        std::lock_guard<std::mutex> lock(_mutex);
        try
        {
            if (start > n_max_DM8s)
            {
                nRet = -1;
                return nRet;
            }
            if (len + start > n_max_DM8s)
            {
                len = n_max_DM8s - start;
            }
            //  len 一定》0
            if (len > 0)
            {
                if (hMapFile_DM8 == INVALID_HANDLE_VALUE)return -2;
                // 映射缓存区视图 , 得到指向共享内存的指针
                LPVOID lpBase = MapViewofFile_New(hMapFile_DM8,fd_dm8,  n_max_DM8s);                  
                // copy 内存
                memcpy(p_DM8, (uchar*)lpBase + start, len);
                //memcpy(p_DM8, DM_8 + start, len);
                // 解除文件映射
                UnMapViewofFile_New(lpBase, n_max_DM8s);                
            }
            else nRet = -1;
        }
        catch (exception& e)
        {
            nRet = -1;
        }
        return nRet;
    }
   

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于OpenMV识别数字及程序说明

OpenMV简介 OpenMV是一个开源、低成本且功能强大的机器视觉模块。它基于STM32F427CPU&#xff0c;集成了OV7725摄像头芯片&#xff0c;能在小巧的硬件模块上&#xff0c;用C语言高效地实现核心机器视觉算法&#xff0c;并提供了Python编程接口&#xff0c;使得图像处理的复杂度…

【教程】lighttpd配置端口反向代理

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 1、修改配置文件&#xff1a; sudo vim /etc/lighttpd/lighttpd.conf2、先添加mod_proxy&#xff1a; 3、然后添加端口映射&#xff1a; 4、保存&…

2024年07年01日 Redis数据类型以及使用场景

String Hash List Set Sorted Set String&#xff0c;用的最多&#xff0c;对象序列化成json然后存储 1.对象缓存&#xff0c;单值缓存 2.分布式锁 Hash&#xff0c;不怎么用到 1.可缓存经常需要修改值的对象&#xff0c;可单独对对象某个属性进行修改 HMSET user {userI…

Transformation(转换)开发-switch/case组件

一、switch/case组件-条件判断 体育老师要做一件非常重要的事情&#xff1a;判断学生是男孩还是女孩、或者是蜘蛛&#xff0c;然后让他们各自到指定的队伍中 体育老师做的事情&#xff0c;我们同样也会在Kettle中会经常用来。在Kettle中&#xff0c;switch/case组件可以来做类似…

河南特岗教师报名流程及免冠照片电子版制作要求

2024年河南特岗教师招聘季又来啦&#xff01;想要成为孩子们心中的超级英雄吗&#xff1f;想要在教育的田野上播种希望吗&#xff1f;那就不要错过这次机会&#xff0c;今年全省共招聘特岗教师3495名&#xff08;具体岗位设置参见《河南省2024年特岗教师招聘岗位设置》&#xf…

盒子模型(笔记)

盒子模型 盒子模型的属性 padding属性 内边距&#xff1a;盒子的边框到内容的距离 /*每个方向内边距*/padding-top: 20px;padding-left:20px;padding-bottom:20px;padding-right: 20px; /*每个方向内边距的第二种方法*/ /* 顺序依次是上左右下*/padding: 10px 20px 30px 4…

02:vim的使用和权限管控

vim的使用 1、vim基础使用1.1、vim pathname 2、vim高级用法2.1、查找2.2、设置显示行号2.3、快速切换行2.4、 行删除2.5、行复制粘贴 3、权限管理3.1、普通用户和特权用户3.2、文件权限表示 vim是Linux中的一种编辑器&#xff0c;类似于window中的记事本&#xff0c;可以对创建…

TP8/6 更改后台入口地址admin改为myadmin 隐藏真实后台网址

原来www.xxx.com/admin 改后www.xxx.com/myadmin config/app.php // 应用映射&#xff08;自动多应用模式有效&#xff09;app_map > [admintest>admin],

【前端VUE】VUE3第一节—vite创建vue3工程

什么是VUE Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0…

卷积层里的填充和步幅

一、定义 1、对于卷积&#xff0c;我们另一个超参数是核的大小&#xff0c;通常使用的卷积核是33或者55&#xff0c;很少用偶数核 2、填充是为了让输出不变或者变大&#xff0c;是为了在输入不太大&#xff0c;又能使模型足够深的情况下使用 3、填充&#xff1a;在输入周围添…

开源软件开发平台哪家好?

进行数字化转型&#xff0c;离不开低代码技术平台等软件产品的加持与助力。因为它更好操作、更灵活、易维护等优势特点突出&#xff0c;在推动企业实现流程化办公的过程中助力明显&#xff0c;作用大&#xff0c;深得客户喜爱。那么&#xff0c;低代码技术平台、开源软件开发平…

居然这么简单就能实现扫雷游戏!

目录 一.思路 1.成果展示 2.思路 二.具体操作 1.创建"棋盘" 2.初始化雷 3.布置雷 4.打印 5.排除雷 三.代码实现 1.test.c文件 2.thunder.h文件 3.thunder.c文件 Hello&#xff0c;大家好&#xff0c;今天我们来实现扫雷游戏&#xff0c;希望这一篇博客能给带给大家一…

HCIA是什么等级的证书

HCIA是华为认证体系中的初级认证&#xff0c;主要用于表明持有者在某一技术领域达到了工程师级别的能力证明。这种认证主要涉及到ICT(信息技术基础设施与通信)设备的安装、配置、运行以及故障排除等方面。 HCIA证书的作用 HCIA证书是进入IT行业的一个初步资格证书&#xff0c;它…

昇思25天学习打卡营第6天|数据变换 Transforms

学习目标&#xff1a;熟练掌握数据变换操作 熟悉mindspore.dataset.transforms接口 实践掌握常用变换 昇思大模型平台学习心得记录&#xff1a; 一、关于mindspore.dataset.transforms 1.1 变换 mindspore.dataset.transforms.Compose将多个数据增强操作组合使用。 mindspo…

【Java】如果让你设计一个分布式链路跟踪系统?你怎么做?

一、问题解析 分布式链路跟踪服务属于写多读少的服务&#xff0c;是我们线上排查问题的重要支撑。我经历过的一个系统&#xff0c;同时支持着多条业务线&#xff0c;实际用上的服务器有两百台左右&#xff0c;这种量级的系统想排查故障&#xff0c;难度可想而知。 因此&#…

Linux文件传输

目录 wget传输 先用我的云服务器vps开放一个端口 目标机wget进行请求下载 指定保存路径 curl传输&#xff08;win11也有&#xff09; ​Netcat传输 文件传输 SFTP传输 连接远程主机 下载远程主机文件 DNS传输 dns带出字符数据命令 拼接hex码进行转字符串 成功转出​…

WIN32核心编程 - 数据类型 错误处理 字符处理

公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 数据类型 基本数据类型 Win32基本数据类型 错误处理 C语言中的错误处理 C中的错误处理 Win32中的错误处理 字符处理 C/C WIN32 字符处理 数据类型 基本数据类型 C/C语言定义了一系列…

umi项目中的一些趣事

前言 出于某些安全问题&#xff0c;需要把HTML中框架注入的umi版本信息去掉&#xff0c;那要怎么搞呢~ 方案 查找官方文档&#xff0c;没发现可以去掉注入信息的方法&#xff0c;但在一番折腾后&#x1f609;终究还是解决了~ 发现 版本信息是从这里注入的~ Object.define…

uboo对内存操作读写命令的基本使用

内存操作命令 直接对DRAM进行读写的操作,uboot常用的内存操作命令有md,nm,mm,mw,cp和cmp. md命令: 显示内存值 # md md - memory display Usage: md [.b, .w, .l, .q] address [# of objects] b:1个字节 byte w:2个字节 world l:4个字节 long of objects 以word 为单位的1…

人工智能--图像语义分割

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a;专业知识 ​ 文章目录 &#x1f349;引言 &#x1f349;介绍 &#x1f348;工作原理 &#x1f34d;数据准备 &#x1f34d;特征提取 &#x1f34d;像素分…