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

embedded/2024/9/23 23:27:10/

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 DMIOhMapFile_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 DM8hMapFile_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 DM16hMapFile_DM16 = CreateFileMapping(INVALID_HANDLE_VALUE,   // 物理文件句柄NULL,   // 默认安全级别PAGE_READWRITE,   // 可读可写0,   // 高位文件大小n_max_DM16s,   // 低位文件大小"ShareMemoryDM16"   // 共享内存名称); #elif defined(linux) || defined(__linux)// specify shared file path// 路径一定要存在,否则会报警// &0 DMIOstring  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 DM8string 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 DM16string 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 filelpBase = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);#endifreturn 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 closemunmap(handle, size);#endifreturn;}
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 一定》0if (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 一定》0if (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;}

http://www.ppmy.cn/embedded/56753.html

相关文章

anaconda中下载压缩包并用conda安装包

有时直接conda安装包时会出错&#xff1b;报错PackagesNotFoundError: The following packages are not available from current channels 比如 conda install -y bioconda::ucsc-gtftogenepred #直接安装报错 #直接下载压缩包安装https://blog.csdn.net/weixin_45552562/ar…

C/C++连接MySQL

今天刚学习了MySQL,于是去尝试能否让C/C连接上MySQL,一番尝试后也是成功了&#xff0c;把经验分享给大家&#xff01; 1.首先我们需要找到MySQL所在的目录下&#xff0c;一般默认安装路径都在C:\Program Files\MySQL\MySQL Server 8.0下&#xff1b; 2.随后我们打开Visual Stu…

LeetCode415-字符串相加

题目 代码 public String addStrings(String num1, String num2) {if (num1 null) {return num2;}if (num2 null) {return num1;}int min Math.min(num1.length(), num2.length());int abs Math.abs(num1.length() - num2.length());// 0.字符串对齐&#xff08;补0&…

为适配kubelet:v0.4 安装指定版本的docker

系统版本信息 cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) iso 文件下载地址 https://vault.centos.org/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso0.4 版本的kubelet 报错信息记录 E0603 19:00:38.273720 44142 kubelet.go:734] Error synci…

Redies基础篇(一)

Redis 是一个高性能的key-value数据库。Redies支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作&#xff0c;而且这些操作都是原子性的&#xff…

编程新纪元:AI辅助工具豆包Marscode体验

自从ChatGPT带动全球AI热潮&#xff0c;AI席卷着各行各业。编程界也不例外&#xff0c;早期做过了Github Copilot、阿里的通义灵码等AI编程插件的体验 p.s.以上的下载量与评分均只是plugins.jetbrains的marketplace数据&#xff0c;仅供参考 基本AI编程工具的功能都差不多&…

GitHub Copilot API

1. 引言 GitHub Copilot&#xff1a;智能编程的革新者 在软件开发的浩瀚宇宙中&#xff0c;GitHub Copilot犹如一颗璀璨的新星&#xff0c;以其独特的魅力引领着智能编程的新纪元。作为GitHub与OpenAI合作推出的革命性工具&#xff0c;Copilot不仅仅是一个简单的代码补全插件…

Vue异步操作发送AJAX请求

5. Vue异步操作 1 axios介绍 在Vue中发送异步请求&#xff0c;本质上还是AJAX。我们可以使用axios这个插件来简化操作&#xff01; 使用步骤 1.引入axios核心js文件。 2.调用axios对象的方法来发起异步请求。 3.调用axios对象的方法来处理响应的数据。 axios常用方法 代码…