提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
转帖|其它|编辑:郝浩|2010-07-12 11:51:44.000|阅读 2176 次
概述:为了进一步提高数据交换的速度,可以采用由系统页文件支持的内存映射文件而直接在内存区域使用,显然这种共享内存的方式是完全可以满足在进程间进行大数据量数据快速传输任务要求的。下面给出在两个相互独立的进程间通过文件映射对象来分配和访问同一个共享内存块的应用实例。
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
共享内存的使用
在Windows操作系统下,任何一个进程不允许读取、写入或是修改另一个进程的数据(包括变量、对象和内存分配等),但是在某个进程内创建的文件映射对象的视图却能够为多个其他进程所映射,这些进程共享的是物理存储器的同一个页面。因此,当一个进程将数据写入此共享文件映射对象的视图时,其他进程可以立即获取数据变更情况。为了进一步提高数据交换的速度,还可以采用由系统页文件支持的内存映射文件而直接在内存区域使用,显然这种共享内存的方式是完全可以满足在进程间进行大数据量数据快速传输任务要求的。下面给出在两个相互独立的进程间通过文件映射对象来分配和访问同一个共享内存块的应用实例。在本例中,由发送方程序负责向接收方程序发送数据,文件映射对象由发送方创建和关闭,并且指定一个唯一的名字供接收程序使用。接收方程序直接通过这个唯一指定的名字打开此文件映射对象,并完成对数据的接收。
在发送方程序中,首先通过CreateFileMapping()函数创建一个内存映射文件对象,如果创建成功则通过 MapViewOfFile()函数将此文件映射对象的视图映射进地址空间,同时得到此映射视图的首址。可见,共享内存的创建主要是通过这两个函数完成的。这两个函数原形声明如下:
HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName); LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap); |
CreateFileMapping()函数参数hFile指定了待映射到进程地址空间的文件句柄,如果为无效句柄则系统会创建一个使用来自页文件而非指定磁盘文件存储器的文件映射对象。很显然,在本例中为了数据能快速交换,需要人为将此参数设定为INVALID_HANDLE_VALUE;参数flProtect设定了系统对页面采取的保护属性,由于需要进行读写操作,因此可以设置保护属性PAGE_READWRITE;双字型参数 dwMaximumSizeHigh和dwMaximumSizeLow指定了所开辟共享内存区的最大字节数;最后的参数lpName用来给此共享内存设定一个名字,接收程序可以通过这个名字将其打开。MapViewOfFile()函数的参数hFileMappingObject为 CreateFileMapping()返回的内存文件映像对象句柄;参数dwDesiredAccess再次指定对其数据的访问方式,而且需要同 CreateFileMapping()函数所设置的保护属性相匹配。这里对保护属性的重复设置可以确保应用程序能更多的对数据的保护属性进行有效控制。下面给出创建共享内存的部分关键代
hRecvMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 1000000, "DataMap"); if (hRecvMap != NULL) { lpData = (LPBYTE)MapViewOfFile(hRecvMap, FILE_MAP_WRITE, 0, 0, 0); if (lpData == NULL) { CloseHandle(hRecvMap); hRecvMap = NULL; } } // 通知接收程序内存文件映射对象的视图已经打开 HWND hRecv = ::FindWindow(NULL, DECODE_PROGRAMM); if (hRecv != NULL) ::PostMessage(hRecv, WM_MAP_OPEN, 0, 0); |
数据的传送实际是将数据从发送方写到共享内存中,然后由接收程序及时从中取走即可。数据从发送方程序写到共享内存比较简单,只需用 memcpy()函数将数据拷贝过去,关键在于能及时通知接收程序数据已写入到共享内存,并让其即使取走。在这里仍采取消息通知的方式,当数据写入共享内存后通过PostMessage()函数向接收方程序发送消息,接收方在消息响应函数中完成对数据的读取:
// 数据复制到共享内存 memcpy(lpData, RecvBuf, sizeof(RecvBuf)); // 通知接收方接收数据 HWND hDeCode = ::FindWindow(NULL, DECODE_PROGRAMM); if (hDeCode != NULL) ::PostMessage(hDeCode, WM_DATA_READY, (WPARAM)0, (LPARAM)sizeof(RecvBuf)); |
当数据传输结束,即将退出程序时,需要将映射进来的内存文件映射对象视图卸载和资源的释放等处理。这部分工作主要由 UnmapViewOfFile()和CloseHandle()等函数完成:
HWND hDeCode = ::FindWindow(NULL, DECODE_PROGRAMM); if (hDeCode != NULL) ::PostMessage(hDeCode, WM_MAP_CLOSE, 0, 0); if (lpData != NULL) { UnmapViewOfFile(lpData); lpData = NULL; } if (hRecvMap != NULL) { CloseHandle(hRecvMap); hRecvMap = NULL; } |
在接收程序中,在收到由发送放发出的WM_MAP_OPEN消息后,由OpenFileMapping()函数打开由名字"DataMap"指定的文件映射对象,如果执行成功,继续用MapViewOfFile()函数将此文件映射对象的视图映射到接收应用程序的地址空间并得到其首址:
m_hReceiveMap = OpenFileMapping(FILE_MAP_READ, FALSE, "DataMap"); if (m_hReceiveMap == NULL) return; m_lpbReceiveBuf = (LPBYTE)MapViewOfFile(m_hReceiveMap,FILE_MAP_READ,0,0,0); if (m_lpbReceiveBuf == NULL) { CloseHandle(m_hReceiveMap); m_hReceiveMap=NULL; } |
当发送方程序将数据写入到共享内存后,接收方将收到消息WM_DATA_READY,在响应函数中将数据从共享内存复制到本地缓存中,再进行后续的处理。同发送程序类似,在接收程序数据接收完毕后,也需要用UnmapViewOfFile()、CloseHandle()等函数完成对文件视图等打开过资源的释放:
// 从共享内存接收数据 memcpy(RecvBuf, (char*)(m_lpbReceiveBuf), (int)lParam); …… // 程序退出前资源的释放 UnmapViewOfFile(m_lpbReceiveBuf); m_lpbReceiveBuf = NULL; CloseHandle(m_hReceiveMap); m_hReceiveMap = NULL; |
小结
经实际测试,使用共享内存在处理大数据量数据的快速交换时表现出了良好的性能,在数据可靠性等方面要远远高于发送WM_COPYDATA消息的方式。这种大容量、高速的数据共享处理方式在设计高速数传通讯类软件中有着很好的使用效果。本文所述代码在Windows 2000下由Microsoft Visual C++ 6.0编译通过。
//附:在dll中共享数据,在宿主进程中读取共享的数据;以下程序在WinXP Pro + VC6 通过测试
//dll创建共享数据;
// create mapping file
HANDLE hSockSrvRecMap;
LPBYTE lpData;
char DataBuf[128];
hSockSrvRecMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 1024, "SockSrvDataMap");
if (hSockSrvRecMap != NULL)
{
lpData = (LPBYTE)MapViewOfFile(hSockSrvRecMap, FILE_MAP_WRITE, 0, 0, 0);
if (lpData == NULL)
{
CloseHandle(hSockSrvRecMap);
hSockSrvRecMap = NULL;
}
}
for (int i=0; i<128; i++) {
DataBuf[i] = i;
}
memcpy(lpData,DataBuf,sizeof(DataBuf));
//宿主进程读取共享数据;
m_hReceiveMap = OpenFileMapping(FILE_MAP_READ, FALSE, "SockSrvDataMap");
if (m_hReceiveMap == NULL)
return;
m_lpbReceiveBuf = (LPBYTE)MapViewOfFile(m_hReceiveMap,FILE_MAP_READ,0,0,0);
if (m_lpbReceiveBuf == NULL)
{
CloseHandle(m_hReceiveMap);
m_hReceiveMap=NULL;
}
for (int i=0; i<18; i++) {
TRACE("%d ",*(m_lpbReceiveBuf++));
}
TRACE("\n mapping data dump complete.\n");
// 不需要内存映射的时候要关闭,两边都需要关闭内存映射文件
if (m_lpbReceiveBuf != NULL)
{
UnmapViewOfFile(m_lpbReceiveBuf);
m_lpbReceiveBuf = NULL;
}
if (m_hReceiveMap != NULL)
{
CloseHandle(m_hReceiveMap);
m_hReceiveMap = NULL;
}
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自:博客面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@pclwef.cn
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢