当前位置: 首页 > news >正文

5、在共享内存无指针编程:句柄HANDLE转换为指针

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        共享内存里面不能用指针,只能用索引,在windows上经常称之为句柄(当然实际上句柄也并非索引,而是个抽象ID),我在这个系统里使用HANDLE这个名字(因为我是windows出身)。

        但是我们真的要无指针编程吗?那还要什么++?

目录

一、索引如何转换为指针

二、句柄结构

三、代码解读


一、索引如何转换为指针

        没有指针当然是很困难的,不过我们是C++啊,我们可以把索引包装得跟指针差不多。

        但是索引只有一个整数偏移量,而转为指针必须知道起始地址,怎么传递起始地址?增加参数还能当指针使用吗?这要怎么搞呢?

        但是我们是共享内存呀!共享内存是公共资源,不可能随意创建,系统内的共享内存都是被管理的,我们只需要给每个共享内存一个唯一的名字,用全局变量保存其起始地址,那么就可以把索引转换为指针而不需要额外的参数了。(这算是一个花招吧)

        前面介绍共享内存管理接口的时候,提到了共享内存的名字,除了名字,还有一个PI(指针索引),每个共享内存块都有预定义的唯一的名字和索引,另外有一个全局数组存储共享内存入口地址。

二、句柄结构

	template<typename T, int PI_N >struct T_HANDLE_ARRAY{T_SHM_SIZE handle;T_HANDLE_ARRAY(T_SHM_SIZE h = -1) :handle(h) {}T_HANDLE_ARRAY(T_HANDLE_ARRAY const& tmp) :handle(tmp.handle) {}typedef random_access_iterator_tag iterator_category;typedef T* pointer;typedef T element_type;typedef T value_type;typedef long difference_type;typedef long offset_type;typedef T& reference;bool operator<(T_HANDLE_ARRAY const& tmp)const { return handle < tmp.handle; }T_HANDLE_ARRAY operator + (long n)const{T_HANDLE_ARRAY tmp;tmp.handle = handle + n;return tmp;}T_HANDLE_ARRAY operator - (long n)const{T_HANDLE_ARRAY tmp;tmp.handle = handle - n;return tmp;}T_SHM_SIZE operator - (T_HANDLE_ARRAY const& tmp)const { return handle - tmp.handle; }T_HANDLE_ARRAY& operator += (T_SHM_SIZE n) { handle += n; return *this; }T_HANDLE_ARRAY& operator ++ () { ++handle; return *this; }T_HANDLE_ARRAY& operator -- () { --handle; return *this; }T_HANDLE_ARRAY& operator = (T_HANDLE_ARRAY const& tmp) { handle = tmp.handle; return *this; }bool operator == (T_HANDLE_ARRAY const& tmp)const { return handle == tmp.handle; }bool operator != (T_HANDLE_ARRAY const& tmp)const { return !((*this) == tmp); }T& operator * ()const{return *operator ->();}T* operator -> ()const{if (0 == PI_N)throw "SHM PI_N=0";struct_T_ARRAY_VMAP_S* pvmap = (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap = &GET_SHM_PRIVATE_DATA(PI_N);for (long i = 0; i < pvmap->size; ++i){if (pvmap->m_vmaps[i].handle_begin <= handle && handle < pvmap->m_vmaps[i].handle_end){if (pvmap->size > paddrmap->addr_map_size){if (0 != paddrmap->thread_mutex.lock())throw "paddrmap->thread_mutex.lock error";if (pvmap->size > paddrmap->addr_map_size){for (long j = paddrmap->addr_map_size; j < pvmap->size; ++j){char* p = CShmMan::ConnectByID(pvmap->m_vmaps[j].shm_id, false);if (NULL == p){thelog << "连接共享内存失败 shmid = " << pvmap->m_vmaps[j].shm_id << " 错误信息:" << strerror(errno) << ende;throw "连接共享内存失败";}if (((unsigned long)p) % 8 != 0){thelog << "地址对齐错误" << ende;throw "地址对齐错误";}char buf[256];sprintf(buf, "连接共享内存 %d %ld shm_id %d addr %p", PI_N, j, pvmap->m_vmaps[j].shm_id, p);thelog << buf << endi;paddrmap->AddShmMap(pvmap->m_vmaps[j].shm_id, p);}}else{thelog << "已经被其它线程处理" << endi;}if (0 != paddrmap->thread_mutex.unlock())throw "paddrmap->thread_mutex.unlock error";}return (T*)paddrmap->shm_addr_map[i].second + handle - pvmap->m_vmaps[i].handle_begin;}if (i == pvmap->size - 1 && handle == pvmap->m_vmaps[i].handle_end){thelog << "刚好越过最后一个 " << handle << " " << (T*)paddrmap->shm_addr_map[i].second + handle - pvmap->m_vmaps[i].handle_begin << endi;//return (T *)paddrmap->shm_addr_map[i].second+handle-pvmap->m_vmaps[i].handle_begin;}}char buf[2048];sprintf(buf, "->无效的句柄 PI_N=%d handle=%ld", PI_N, handle);theLog << "shmArray.h T_HANDLE_ARRAY" << buf << ende;ShowVMapPrivateData();abort();return NULL;}static T_SHM_SIZE _me(T const* p, bool not_throw = false){char buf[256];struct_T_ARRAY_VMAP_S* pvmap = (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap = &GET_SHM_PRIVATE_DATA(PI_N);for (long i = 0; i < pvmap->size; ++i){if ((T*)paddrmap->shm_addr_map[i].second <= p && p < (T*)paddrmap->shm_addr_map[i].second + pvmap->m_vmaps[i].handle_end - pvmap->m_vmaps[i].handle_begin){return p - (T*)paddrmap->shm_addr_map[i].second + pvmap->m_vmaps[i].handle_begin;}if (i == pvmap->size - 1 && p == (T*)paddrmap->shm_addr_map[i].second + pvmap->m_vmaps[i].handle_end - pvmap->m_vmaps[i].handle_begin){thelog << "刚好越过最后一个 " << p << " " << p - (T*)paddrmap->shm_addr_map[i].second + pvmap->m_vmaps[i].handle_begin << endi;//return p-(T *)paddrmap->shm_addr_map[i].second+pvmap->m_vmaps[i].handle_begin;}}if (not_throw)return -1;else{sprintf(buf, "_me无效的地址 %p", p);throw buf;}}static void ShowVMapPrivateData(){struct_T_ARRAY_VMAP_S* pvmap = (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap = &GET_SHM_PRIVATE_DATA(PI_N);long i, j;theLog << endl;theLog << "pvmap->size=" << pvmap->size << endl;for (i = 0; i < pvmap->size; ++i){theLog << i << " : begin=" << pvmap->m_vmaps[i].handle_begin << " end=" << pvmap->m_vmaps[i].handle_end << endl;}theLog << "paddrmap->addr_map_size=" << paddrmap->addr_map_size << endl;for (j = 0; j < paddrmap->addr_map_size; ++j){theLog << j << " : " << paddrmap->shm_addr_map[j].first << " - " << (long)paddrmap->shm_addr_map[j].second << endl;}theLog << endi;}};

三、代码解读

        这个代码是个模板,参数是指向的类型和入口指针的索引。

        主要部分是自定义的指针类,符合随机迭代器概念要求,可以用在STL算法里。

        复杂的代码部分是在没有连接是自动去连接。由于每个共享内存结构其实是可扩展的,是多个共享内存的串联,因此代码比较复杂。数据的索引是连续的,但不同分块的连接地址并不相同,因此需要一个分块映射表。还要考虑多线程保护。如果没有分块问题,操作会简单很多,只需要根据PI_N获取入口地址,判断是否需要连接,然后就能转换为指针了。


(这里是文档结束)

相关文章:

5、在共享内存无指针编程:句柄HANDLE转换为指针

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 共享内存里面不能用指针&#…...

hive动态分区导致xceivercount超限,hdfs无法创建新连接

目录 一、事件复盘&#xff1a; 二、解决方案&#xff1a; 三、讨论 一、事件复盘&#xff1a; hdfs无法创建新的文件&#xff0c;xceivercount超过最大设置&#xff0c;平时每个datanode只有100个左右的连接&#xff0c;突然达到8000以上。 事故原因&#xff0c;跨多天的…...

如何识别Android init 中的缓慢操作

Android 14 开机时间优化措施汇总-CSDN博客 Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客Android系统设置kernel log level的…...

JVM:常用工具总结

文章目录 一、jstat工具 一、jstat工具 Jstat工具是JDK自带的一款监控工具&#xff0c;可以提供各种垃圾回收、类加载、编译信息等不同的数据。使用方法为&#xff1a;jstat -gc进程ID每次统计的时间间隔&#xff08;毫秒&#xff09;统计次数。 C代表Capacity容量&#xff0c…...

二染色,CF 1594D - The Number of Imposters

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1594D - The Number of Imposters 二、解题报告 1、思路分析 并查集&…...

Go语言并发编程-Channel通信_2

Channel通信 Channel概述 不要通过共享内存的方式进行通信&#xff0c;而是应该通过通信的方式共享内存 这是Go语言最核心的设计模式之一。 在很多主流的编程语言中&#xff0c;多个线程传递数据的方式一般都是共享内存&#xff0c;而Go语言中多Goroutine通信的主要方案是Cha…...

Richteck立锜科技电源管理芯片简介及器件选择指南

一、电源管理简介 电源管理组件的选择和应用本身的电源输入和输出条件是高度关联的。 输入电源是交流或直流&#xff1f;需求的输出电压比输入电压高或是低&#xff1f;负载电流多大&#xff1f;系统是否对噪讯非常敏感&#xff1f;也许系统需要的是恒流而不是稳压 (例如 LED…...

Socket 简介与 Java Socket 编程示例

Socket&#xff08;套接字&#xff09;是网络通信中的一个关键概念&#xff0c;它是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 一、定义与概念 基本概念&#xff1a;Socket可以被视为网络环境中进程间通信的API&#xff08;应用程序编程接口&#xff09;&…...

跟着操作,解决iPhone怎么清理内存难题

在如今智能手机功能日益强大的时代&#xff0c;我们使用手机拍照、录制视频、下载应用、存储文件等操作都会占用手机内存。当内存空间不足时&#xff0c;手机运行会变得缓慢&#xff0c;甚至出现卡顿、闪退等现象。因此&#xff0c;定期清理iPhone内存是非常必要的。那么&#…...

React、Vue的password输入框组件,如何关闭自动填充?

有时候我们的表单使用了一个password组件&#xff0c;这时候每次打开新建&#xff0c;都会自动获取浏览器缓存的密码&#xff0c;但是它的上一个input输入框并不是用户名&#xff0c;这时候我们希望我们的表单&#xff0c;每次点开的时候密码是空的&#xff0c;让用户自动输入&…...

HTML+JS+CSS计算练习

可填 题目数量 数字范围 计算符号 题目做完后会弹窗提示正确率、用时 效果图 源代码在图片后面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…...

设计模式使用场景实现示例及优缺点(行为型模式——责任链模式)

在一个遥远的森林深处&#xff0c;有一个和谐的动物王国。这个王国里的动物们都有各自的职责&#xff0c;大家相互合作&#xff0c;共同维护着森林的和平与繁荣。 一天&#xff0c;森林里来了一只迷路的小兔子&#xff0c;她焦急地四处张望&#xff0c;不知道该怎么办。于是&am…...

CSS-1_0 CSS和文档流

文章目录 CSS和文档流如何证明这个流的存在呢&#xff1f;流和display番外&#xff1a;inline-block 碎碎念 CSS和文档流 首先什么叫流呢&#xff1f; 通常来说&#xff0c;我们最终看到的网页是HTML文档中定义的各个元素挨个输出的结果&#xff0c;这种一个接一个输出的方式…...

小程序图片下载保存方法,图片源文件保存!

引言 现在很多时候我们在观看到小程序中的图片的时候&#xff0c;想保存图片的原文件格式的话&#xff0c;很多小程序是禁止保存的&#xff0c;即使是让保存的话&#xff0c;很多小程序也会限制不让保存原文件&#xff0c;只让保存一些分辨率很低的&#xff0c;非常模糊的图片…...

新书速览|深入理解Hive:从基础到高阶:视频教学版

《深入理解Hive&#xff1a;从基础到高阶&#xff1a;视频教学版》 本书内容 《深入理解Hive:从基础到高阶:视频教学版》采用“理论实战”的形式编写&#xff0c;通过大量的实例&#xff0c;结合作者多年一线开发实战经验&#xff0c;全面地介绍Hive的使用方法。《深入理解Hiv…...

钡铼Profinet、EtherCAT、Modbus、MQTT、Ethernet/IP、OPC UA分布式IO系统BL20X系列耦合器

BL20X系列耦合器是钡铼技术开发的一款用于分布式I/O系统的设备&#xff0c;专为工业环境下的高速数据传输和远程设备控制而设计&#xff0c;支持多种工业以太网协议&#xff0c;包括Profinet、EtherCAT、Modbus、MQTT、Ethernet/IP和OPC UA等。如果您正在考虑部署BL20X系列耦合…...

Git分支合并以及分支部分合并 提交记录合并

Git分支合并,以及分支部分合并,提交记录合并 最近工作中用到git分支合并的场景,记录一下. 分支整体合并,合并所有记录 仅合并分支部分代码...

IDEA关联数据库

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …...

【Leetcode】14. 最长公共前缀

leetcode原地址&#xff1a;https://leetcode.cn/problems/longest-common-prefix 描述 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 示例 1&#xff1a; 输入&#xff1a;strs [“flower”,“flow”,“flight”…...

【BUG】已解决:zipfile.BadZipFile: File is not a zip file

已解决&#xff1a;zipfile.BadZipFile: File is not a zip file 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发…...

小白新手搭建个人网盘

小白新手搭建个人网盘 序云服务器ECS重置密码远程连接ECS实例 安装OwnCloud安装Apache服务PHP运行环境NAS挂载挂载验证操作体验 序 阿里云文件存储NAS&#xff08;Apsara File Storage NAS&#xff09;是一个可大规模共享访问&#xff0c;弹性扩展的分布式文件系统。本文主要是…...

NineData全面支持PostgreSQL可视化表结构设计

“PostgreSQL 是最像 Oracle 的开源关系型数据库“&#xff0c;也正因为如此&#xff0c;很多企业都青睐 PostgreSQL&#xff0c;拿它当成 Oracle 的替代品。所以毫无疑问&#xff0c;目前 PostgreSQL 在企业中非常常见。 对于直接接触 PostgreSQL 的开发人员而言&#xff0c;…...

从系统层面认识Linux及mysql中的多表查询

为什么计算机起始时间是1970年1月1日 为什么计算机起始时间是1970年1月1日-CSDN博客https://blog.csdn.net/csdn_kou/article/details/81535452 date "%Y-%m-%d %H:%M:%S" 查看日期 sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 在数据层面 CPU不…...

PCB(印制电路板)制造涉及的常规设备

印制电路板&#xff08;PCB&#xff09;的制造涉及多种设备和工艺。从设计、制作原型到批量生产&#xff0c;每个阶段都需要不同的专业设备。以下是一些在PCB制造过程中常见的设备&#xff1a; 1. 计算机辅助设计&#xff08;CAD&#xff09;软件&#xff1a; - 用于设计PC…...

《Windows API每日一练》10.3 公用对话框

Windows最初发行时的主要目标之一就是提倡一种标准化的用户界面。对于公用菜单 项来说&#xff0c;这一目标实现得很快。几乎所有的软件制造商都采用了Alt-File-Open组合来打开 文件。但是&#xff0c;真正用来打开文件的对话框却经常很不一样。 从Windows 3.1开始&#xff0c…...

C++中的引用

在C中&#xff0c;我们要学习一个新的概念&#xff0c;叫做引用。引用不是对象&#xff0c;它只是给变量取一个别名。就好比&#xff0c;我们每个人总会右一下外号&#xff0c;或者是小名。当朋友或者家长不管是直接叫你的名字&#xff0c;还是叫你的小名&#xff0c;你都会答应…...

【自学安全防御】三、企业双机热备和带宽管理的综合实验

实验拓扑&#xff1a; 实验任务&#xff1a; 12&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 13&#xff0c;办公区上网用户限制流…...

无极与有极电容的区别

无极性电容与有极性电容&#xff1a;差异与应用探索 在电子元件的广阔世界里&#xff0c;电容器无疑是不可或缺的一部分。它们以储存电荷和调节电路中的电压与电流而闻名。然而&#xff0c;电容器并非一概而论&#xff0c;其中最为显著的区别之一就是无极性电容与有极性电容。…...

入坑树莓派(2)——树莓派4B与手机蓝牙通信

入坑树莓派(2)——树莓派4B与手机蓝牙通信 1、引言 在入坑树莓派(1)中已经搞掂了可视化问题。现在继续开展下一步,尝试与手机通信,一开始是想弄wifi连接的,但发现基于wifi的APP比较难弄,为了降低开发的难度,又因为树莓派板子自带蓝牙模块,所以直接选用蓝牙连接手机…...

RocketMQ单结点安装/Dashboard安装

目录 1.安装NameServer 2.安装Broker 3.使用自带工具测试数据发送 4.使用DashBoard进行查看 5.关闭相关设备 前置条件&#xff1a;两台虚拟机CentOS Linux release 7.5.1804(ps:当然也可以都部署在一台机器上) RocketMq属于天生集群。需要同时启动nameServer和Broker进行…...

高端网站设计收费/谷歌优化师

数字化时代客户体验管理与卓越厅堂服务课程背景&#xff1a; 数字化浪潮下&#xff0c;很多网点存在以下问题&#xff1a;不清楚如何提升网点数字化客户体验&#xff1f;不清楚网点数字化客户体验应用案例&#xff1f;不积善成德如何打造网点卓越厅堂服务&#xff1f; 课…...

wordpress主题框架Genesis/网上怎么推销自己的产品

在微软平台上&#xff0c;想追求新鲜是越来越不容易了&#xff01; 昨晚在家&#xff0c;想试一把WPF&#xff0c;到微软网站上去下载orcas最新的版本&#xff0c;发现竟有8个img文件需要下载。想这将来卸载时&#xff0c;也要花不少时间吧&#xff0c;于是就准备下那个base im…...

58同城网招聘找工作建筑工程/佛山seo外包平台

磁盘阵列df -h看文件系统使用率 : format看可用磁盘 : cfgadm -al看总线连接...

做网站优化的话术/在线crm软件

这里有几个定义需要说一下&#xff0c;外设&#xff0c;顾名思义&#xff0c;就是IC芯片所接的能够与IC通信的外部设备。早起由于IC集成工艺不发达&#xff0c;很多东西都是外设的&#xff0c;在此以DSP芯片为例&#xff0c;比如PWM、ADC、CAN等等&#xff0c;原本都是需要芯片…...

做电商网站需要多少钱/网页广告调词平台多少钱

学习目标&#xff1a; Python学习九、 学习内容&#xff1a; 1、返回函数 2、匿名函数 3、装饰器 4、偏函数 1、返回函数 高阶函数除了可以接受函数作为参数外&#xff0c;还可以把函数作为结果值返回&#xff0c;当我们调用某一返回函数时&#xff0c;调用的不是结果而是函…...

如何去门户网站做推广呢/百度公司有哪些部门

<pre name"code" class"html">/* 需求&#xff1a;编写一个js文件&#xff0c;在js文件中自定义一个数组工具对象&#xff0c; 该工具对象要有一个找到最大值的方法&#xff0c;与找元素对应的索引值的方法。 */这个代码在ArrayTool.js文件中 //创建…...