一.CreateFileMapping实现的共享内存及用法

共享内存概念

1.在32位的Windows系统中,每一个进程都有权访问他自己的4GB(232=4294967296)平面地址空间,没有段,没有选择符,没有near和far指针,没有near和far函数调用,也没有内存模式。

2.每个进程都有独立的4GB逻辑地址空间,32位的Windows系统允许每一个进程独立访问自己的内存,即独立于其它进程,也即它自己的32位逻辑地址空间。操作系统将把每一个进程的逻辑地址转换成实际的物理地址,独立的地址空间可以使其他已经出错的进程之间相互隔离,入阁一个进程通过他自己的内存空间处理数据,其他的进程就比在DOS中安全,在DOS中的所有应用程序共享相同的物理内存空间,虽然这带来了许多好处,但在不同进程之间转的指针,就会出现一些麻烦。在一个进程中,一个给定的逻辑地址将与另一进程的指针不会有相同的逻辑地址。

3.那么怎么样才能在32位的Windows系统中达到共享内存的目的呢?

4.随着进程的分离内存空间的出现,进程不能简单地使用GlobalAlloc()函数来分配内存,并把它转递给另一个进程来共享,一个进程检查有另一个进程分配的指针,他只是指向随机地址。然而,在32位的Windows系统支持在进程间共享内存映象文件,可以通过内存映象文件来达到内存共享的目的。

5.32位的Windows系统的虚拟内存系统具有把实际内存映象到页面文件或交换文件的能力.通过把内存映象到任何想映象的文件,包括系统页面本身,应用程序就可以拓展这种能力。文件影响能用来提供更快更简捷的文件访问方式,并提供内存共享。

6.然后把文件映像到内存,首先必须调用CreateFileMapping()函数,然后再调用MapViewOfFile函数,把文件视映像到进程地址空间上。

使用方法

1.要把文件映像到内存,首先必须调用CreateFileMapping()函数,它需要用一个由CreateFile()函数打开并返回的文件句柄,对大多数共享内存应用程序。必须把此句柄设置为0xFFFFFFFF,用来指定系统页面文件。通过使用上面的特殊句柄,可以不调用CreateFile函数,当然在完成时,也不必有一个内存的磁盘文件拷贝。

2.CreateFileMapping()函数的第二个参数是一个指向SECURITY_ATTRIBUTES结构的指针,它指明返回的句柄是否可以被子进程所继承。另外,在SECURITY_ATTRIBUTES结构中,也包括一个安全性描述的子指针,它由WinNT支持它的安全机制。

3.第三个参数允许指定内存块的访问权限,权限值有PAGE_READONLY、PAGE_READWRITE和PAGE_WRITECOPY,PAGE_WRITECOPY可以在指定页面上拷贝并写访问。这意味着当一个进程映像此内存并写入时,它将得到自己修改数据的拷贝,面不是写到共享内存空间,另外,可以把几个标志一起使用来指定其他部分的属性。

4.其他参数允许指定内存块的最大尺寸,如果内存块的尺寸比第一个 参数中指定的文件尺寸还要大,这个文件就增大。

5.最后一个参数为内存映像对象指定名字,通过调用CreateFileMapping函数和OpenFileMapping函数,其他进程可用这个名字来访问相同的文件映像。

6.一旦一个内存映像对象由CreateFileMapping()创建成功,可以调用MapViewOfFile函数把文件视映像到进程地址空间上,这个函数需要用一个由CreateFileMapping()函数或OpenFileMapping()函数返回的句柄,并允许指定访问模式和映像的字节数,以及文件映像对象中的偏移量。另外,还可以使用MapViewOfFileEx()函数来实现同样的功能,只是此函数还允许指定映像对象的起始地址。

7.当用完映像文件后,可以通过调用UnmapViewOfFile函数,释放映像内存并把一些映像数据写入文件(除非它是交换文件),如果想立即把数据写回磁盘文件,那就需要调用FlushViewOfFile()函数把映像内存写入文件。

8.为了便于读者对以上程序的理解和进行下一步的学习,这里再简单介绍一下Win32内存模式。在开始学习Win32内存管理之前,最好先了解一些16位Windows与32位Windows的区别,它们之间的主要区别是把寄存器和指针长度变为32位。

9.Win32 API允许应用程序访问虚拟内存,如果想保存大量的数据,这十分有用,尽管大部分空间从来没有用于物理存储。虚拟内存页有四种状态,提交页面被分配一个物理存储单元,不管它是在是在交换文件中,提交页面被锁定后就强行留在内存中,直到解锁为止。保留页面存储一块保留地址国,它不被分配任何存储单元,自由页面都没有用。

10.VirtualAlloc()函数可用来分配从指定逻辑内存开始的一定范围内的地址,该函数的另一个参数允许指定访问保护标志,并指定内存是否被保存或被用于物理存储单元,也可以调用此函数来调配前面保存的虚拟内存页。

11.可以通过调用GloballLock()函数来强制使内存块留在物理内存中,应该谨慎使用此函数,因为它阻止系统管理这块内存,直到调用GlobalUnlock()函数为止。如果一个进程锁定了一大块内存,其他进程就会终止,不管还有多少内存。

12.函数VirtualProtect()用于改变一块内存的访问权限,VirtualQuery()函数返回内存页的住处。如果想访问其他进程的页面,可以通过调用VirtualProtecteEx和VirutalQueryEx两个函数来实现。

函数解析

1.CreateFileMapping

HANDLE CreateFileMapping(
HANDLE hFile,                       //物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
DWORD flProtect,                      //保护设置
DWORD dwMaximumSizeHigh,                      //高位文件大小
DWORD dwMaximumSizeLow,                      //低位文件大小
LPCTSTR lpName                      //共享内存名称
);
hFile是创建共享文件的句柄。
lpFileMappingAttributes是文件共享的属性。
flProtect是当文件映射时读写文件的属性。
dwMaximumSizeHigh是文件共享的大小高位字节。
dwMaximumSizeLow是文件共享的大小低位字节。
lpName是共享文件对象名称。
hFileMappingObject是共享文件对象。
dwDesiredAccess是文件共享属性。
dwFileOffsetHigh是文件共享区的偏移地址。
dwFileOffsetLow是文件共享区的偏移地址。
dwNumberOfBytesToMap是共享数据长度。

2.主要前3个参数说明

2.1.物理文件句柄任何可以获得的物理文件句柄, 如果你需要创建一个物理文件无关的内存映射也无妨, 将它设置成为 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

2.2.如果需要和物理文件关联, 要确保你的物理文件创建的时候的访问模式和"保护设置"匹配, 比如: 物理文件只读, 内存映射需要读写就会发生错误. 推荐你的物理文件使用独占方式创建.

2.3.如果使用 INVALID_HANDLE_VALUE, 也需要设置需要申请的内存空间的大小, 无论物理文件句柄参数是否有效, 这样 CreateFileMapping 就可以创建一个和物理文件大小无关的内存空间给你, 甚至超过实际文件大小, 如果你的物理文件有效, 而大小参数为0, 则返回给你的是一个和物理文件大小一样的内存空间地址范围. 返回给你的文件映射地址空间是可以通过复制, 集成或者命名得到, 初始内容为0.

2.4.保护设置就是安全设置, 不过一般设置NULL就可以了, 使用默认的安全配置. 在win2k下如果需要进行限制, 这是针对那些将内存文件映射共享给整个网络上面的应用进程使用是, 可以考虑进行限制.

综合应用场景

1.在开发软件过程里,也经常碰到进程间共享数据的需求。比如A进程创建计算数据,B进程进行显示数据的图形。

2.这样的开发方式可以把一个大程序分开成独立的小程序,提高软件的成功率,也可以更加适合团队一起开发,加快软件的开发速度。下面就来使用文件映射的方式进行共享数据。

3.先要使用函数CreateFileMapping来创建一个想共享的文件数据句柄,然后使用MapViewOfFile来获取共享的内存地址,

4.然后使用OpenFileMapping函数在另一个进程里打开共享文件的名称,这样就可以实现不同的进程共享数据。

void FileMapping(void)
{
	 //打开共享的文件对象。
	 m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,_T("didaxueyuan"));
	 if (m_hMapFile)
	 {
		   //显示共享的文件数据。
		   LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,,,);
		   OutputDebugString(lpMapAddr);
	 }
	 else
	 {
		   //创建共享文件。
		   m_hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,,,_T("TestFileMap"));

		   //拷贝数据到共享文件里。
		   LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,,,);
		   std::wstring strTest(_T("TestFileMap"));
		   wcscpy(lpMapAddr,strTest.c_str());

		   FlushViewOfFile(lpMapAddr,strTest.length()+);
	 }
}

解析说明代码例子

1.与虚拟内存类似,保护方式可以是PAGE_READONLY或是PAGE_READWRITE。如果多进程都对同一共享内存进行写访问,则必须保持相互间同步。映射文件还可以指定PAGE_WRITECOPY标志,可以保证其原始数据不会遭到破坏,同时允许其他进程在必要时自由的操作数据的拷贝。

2.在创建文件映射对象后使用可以调用MapViewOfFile函数映射到本进程的地址空间内。

3.下面说明创建一个名为MySharedMem的长度为4096字节的有名映射文件:

HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),NULL,PAGE_READWRITE,0,0x1000,"MySharedMem");

4.并映射缓存区视图:

LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

5.其他进程访问共享对象,需要获得对象名并调用OpenFileMapping函数。

HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,FALSE,"MySharedMem");

6.一旦其他进程获得映射对象的句柄,可以象创建进程那样调用MapViewOfFile函数来映射对象视图。用户可以使用该对象视图来进行数据读写操作,以达到数据通讯的目的。

7.当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:

if (!UnmapViewOfFile(pszMySharedMapView))
{
  MessageBox("卸载映射地址失败");
}

8.好了,今天的一章节就讲到这里,感谢大家的支持285530835

B0220.jpg

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

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

相关文章

修改npm路径

npm config ls如果是第一次使用NPM安装包的话,在配置中只会看到prefix的选项,就是NPM默认的全局安装目录。但是如果有多次使用NPM安装包的话,就会看到cache和prefix两个路径。 新建两个文件夹node_global_modules和node_cache npm config s…

【CesiumJS入门】(7)绘制多段线(动态实时画线)

前言 鼠标左键添加点、右键完成绘制,单击右侧弹窗关闭按钮清空绘制。参考沙盒示例:Drawing on Terrain 直接上代码了 /** Date: 2023-07-12 18:47:18* LastEditors: ReBeX 420659880qq.com* LastEditTime: 2023-07-16 16:26:19* FilePath: \cesium-tyro-blog\s…

Verdi之波形展示nWave

6.nWave 6.1 添加波形文件 1.打开nWave界面,具体操作如下: 2.正式添加波形,使用快捷键G或者点击以下图标,选择需要的信号。 也可以在 n Trace中选中信号后,鼠标中键拖拽,或者ctrlw进行添加; 6…

R和python中dataframe读取方式总结

首先我有一个如图所示的文件 如果在python中读取 import pandas as pd df pd.read_csv("./6group_count.csv",index_col0) df而在R中读取的方式如下 df read.csv("./6group_count.csv",row.names 1)

MySQL---索引

目录 一、索引的分类 二、索引的底层原理是什么? 2.1、Innodb和MyIsAM两种引擎搜索数据时候的区别: 2.2、为什么MySQL(MyIsAM、Innodb)索引选择B树而不是B树呢? 2.3、Innodb的主键索引和二级索引(辅助…

【Ajax】笔记-Ajax案例准备与请求基本操作

案例准备HTML 按钮div <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>AJAX GET 请求</title&g…

2D、3D机器视觉各有优势与局限,融合应用将成工业领域生产新方式

在智能制造的浪潮中&#xff0c;制造行业生产线亟需转型升级&#xff0c;为国内机器视觉市场释放出了惊人的机器视觉技术及产品需求。在自动化工业质量控制和在线检测领域&#xff0c;2D机器视觉与3D机器视觉都具有重要的作用。那在机器视觉自动化场景中该如何选择合适的机器视…

python 乘法口诀

下面是一个用Python打印乘法口诀表的代码&#xff1a; print("乘法口诀表:")for i in range(1, 10):for j in range(1, i1):print(f"{j} {i} {i*j}", end"\t")print()

Blazor前后端框架Known-V1.2.4

V1.2.4 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazor…

【图像处理】Python判断一张图像是否亮度过低,图片模糊判定

文章目录 亮度判断模糊判断 亮度判断 比如&#xff1a; 直方图&#xff1a; 代码&#xff1a; 这段代码是一个用于判断图像亮度是否过暗的函数is_dark&#xff0c;并对输入的图像进行可视化直方图展示。 首先&#xff0c;通过import语句导入了cv2和matplotlib.pyplot模块…

Element-Plus搭建CMS页面结构 引入第三方图标库iconfont(详细)

Element-Plus组件库使用 element plus组件库是由饿了么前端团队专门针对vue框架开发的组件库&#xff0c;专门用于电脑端网页的。因为里面集成了很多组件&#xff0c;所以使用他可以非常快速的帮我们实现网站的开发。 安装&#xff1a; npm install element-plus --save 引入…

jenkins 采用ssh方式连接gitlab连接不上

一、gitlab 添加jenkins服务器的公钥 jenkins 生成秘钥命令 ssh-keygen -t rsa2.jenkins 秘钥地址&#xff1a; cd /root/.ssh3.复制公钥 到gitlab 添加 cat id_rsa_pub4.添加私钥到jenkins cat id_rsa5.绑定&#xff08;顺利的话到这里就结束了&#xff09; &#xff0…

Linux下Lua和C++交互

前言 lua&#xff08;wiki 中文 官方社区&#xff1a;lua-users&#xff09;是一门开源、简明、可扩展且高效的弱类型解释型脚本语言。 由于其实现遵循C标准&#xff0c;它几乎能在所有的平台&#xff08;windows、linux、MacOS、Android、iOS、PlayStation、XBox、wii等&…

【条件与循环】——matlab入门

目录索引 if&#xff1a;else与elseif&#xff1a; for&#xff1a; if&#xff1a; if 条件语句块 endelse与elseif&#xff1a; if 条件代码块 elseif 条件代码块 else 代码块 endfor&#xff1a; for 条件循环体 end在matlab里面类似的引号操作都是包头又包尾的。上面的c…

postman测试接口出现404

postman测试接口出现404 1.用postman调试接口的过程中&#xff0c;出现404的情况&#xff0c;但是接口明明已调到了&#xff0c;而且数据也已经存入数据库了&#xff0c;这让我感到很疑惑。看网上的解决办法检查了我的路径&#xff0c;提交方式、参数类型等都是正确的&#xf…

安装adobe系列产品,提示错误代码81解决办法

安装adobe系列软件&#xff0c;如Photoshop、Premiere Pro、Illustrator等时&#xff0c;出现如下图提示错误代码81&#xff0c;如何解决呢&#xff1f;一起来看看。 解决方法一 (重启电脑等待5分钟再安装&#xff01;) 解决方法二 应用程序中打开Adobe Creative Cloud 点击…

Linux系统终端窗口ctrl+c,ctrl+z,ctrl+d的区别

时常在Linux系统上&#xff0c;执行某命令停不下来&#xff0c;就这几个ctrl组合键按来按去&#xff0c;今天稍微总结下具体差别&#xff0c;便于以后linux系统运维操作 1、ctrlc强制中断程序&#xff0c;相应进程会被杀死&#xff0c;中断进程任务无法恢复执行 2、ctrlz暂停正…

【运维工程师学习】Centos中MySQL替换MariaDB

【运维工程师学习】Centos8中MySQL替换MariaDB 1、查看已有的mysql2、MySQL官网tar包下载3、找到下载路径解压4、移动解压后的文件夹到/usr/local/mysql5、创建data文件夹&#xff0c;一般用于存放数据库文件数据6、创建用户组7、更改用户文件夹权限8、生成my.cnf文件9、编辑my…

ZooKeeper ZAB

文章首发地址 在接收到一个写请求操作后&#xff0c;追随者会将请求转发给群首&#xff0c;群首将探索性地执行该请求&#xff0c;并将执行结果以事务的方式对状态更新进行广播。一个事务中包含服务器需要执行变更的确切操作&#xff0c;当事务提交时&#xff0c;服务器就会将这…

23家企业推出昇腾AI系列新品 覆盖云、边、端智能硬件

[中国&#xff0c;上海&#xff0c;2023年7月6日] 昇腾人工智能产业高峰论坛在上海举办。论坛现场&#xff0c;大模型联合创新启动&#xff0c;26家行业领军企业、科研院所与华为将共同基于昇腾AI进行基础大模型与行业大模型应用创新。同时&#xff0c;华为携手伙伴联合发布昇腾…