网站首页 > 教程分享 正文
内存映射文件技术概述
内存映射文件,是由一个文件到一块内存的映射。Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。
Win32系统允许多个进程(运行在同一计算机上)使用内存映射文件来共享数据,所以,如果一个进程往内存映射文件中写数据,另一个进程来读,就实现了它们之间的通信。实际上,其他共享和传送数据的技术,诸如使用SendMessage或者PostMessage,都在内部使用了内存映射文件。
实现
接下来我们通过C语言编写程序,实现两个进程交换数据(通信)。在本例中,只在同一台主机上实现不同进程间的通信,所以可以使用内存映射文件来实现。
程序基本流程:
1) 新建命名共享
首先利用CreateFile或者CreateFileForMapping获得一个用于映射的物理文件句柄, 然后利用该文件句柄结合CreateFileMapping得到一个命名的共享内存映射文件句柄。
2) 打开命名共享内存
如果需要共享已经存在的命名共享内存映射文件, 使用OpenFileMapping函数。
3) 获得地址空间指针
进行内存映射文件的读写和一般的文件读写不同, 是直接面对你申请的地址空间, 为此需要使用MapViewOfFile得到相关的地址LPVOID类型的指针。 如果需要进行数据写入, 可以通过类型转换直接对于内存地址进行赋值,比如memcpy( lpAddress, lpBuf, ....);如果是读取操作,将参数顺序调整一下就可以了。
4) 将内存复制到所映射的物理文件上面
FlushMapViewOfFile函数可以将内存里面的内容DUMP到物理磁盘上面。
5) 卸载内存映射文件地址指针
UnmapViewOffFile函数来卸内存映射文件。
6) 关闭内存映射文件
最后,调用CloseHandle来关闭内存映射文件。
实现及测试源代码
两个进程一个视为客户端,另一个视为服务端
cilentProcess:
#include "windows.h"
#include "math.h"
#include "stdio.h"
void main()
{
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"ClientProcess");
if (hFileMapping == NULL)
{
CloseHandle(hFileMapping);
hFileMapping = NULL;
return ;
}
// 设定大小、偏移量等参数
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sinf.dwAllocationGranularity;
DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;
// 将文件数据映射到进程的地址空间
PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
// 测试程序
// 在客户端输入一个数字,在服务端计算该数的平方,并将结果返回给客户端;
int dataInClientPro = 0;
printf("**********In ClintProcess**********\n");
while(1)
{
printf("Please input a num (0 for quit):\t\n");
scanf("%d", &dataInClientPro);
if(dataInClientPro == 0)
{
return;
}
memcpy(pbFile,&dataInClientPro,sizeof(int));
memcpy(pbFile+sizeof(int),&dataInClientPro,sizeof(int));
FlushViewOfFile(pbFile,NULL);
Sleep(1000);
memcpy(&dataInClientPro,pbFile+sizeof(int),sizeof(int));
printf("Result form ServerProcess :\t%d\n", dataInClientPro);
}
}
serverProcess:
#include "windows.h"
#include "math.h"
#include "stdio.h"
void main()
{
// 创建文件内核对象,其句柄保存于hFile
HANDLE hFile = CreateFile("Recv1.zip",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
// 创建文件映射内核对象,句柄保存于hFileMapping
HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,
0, 0x4000000, "ClientProcess");
if (hFileMapping != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hFileMapping);
hFileMapping = NULL;
return ;
}
// 设定大小、偏移量等参数
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sinf.dwAllocationGranularity;
DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;
// 将文件数据映射到进程的地址空间
PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,
FILE_MAP_ALL_ACCESS,
(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);
// 测试程序
// 从客户端读入一个数字,在服务端计算该数的平方,并将结果返回给客户端;
int dataInServerPro;
int flag = 0;
memset(pbFile, 0, sizeof(int));
FlushViewOfFile(pbFile,NULL);
while(1)
{
memcpy(&flag, pbFile, sizeof(int));
if(flag)
{
memcpy(&dataInServerPro, pbFile+sizeof(int), sizeof(int));
printf("**********In ServerProcess**********\nRead a num from ClintProcess :\t%d\n",dataInServerPro);
dataInServerPro = dataInServerPro*dataInServerPro;
memcpy(pbFile+sizeof(int),&dataInServerPro,sizeof(int));
FlushViewOfFile(pbFile,NULL);
memset(pbFile, 0,sizeof(int));
FlushViewOfFile(pbFile, NULL);
}
Sleep(1);
}
// 将文件数据从进程的地址空间中释放
UnmapViewOfFile(pbFile);
// 释放文件映射内核对象
CloseHandle(hFileMapping);
// 释放文件内核对象
CloseHandle(hFile);
}
运行结果
猜你喜欢
- 2024-10-24 OpenCV-Python滚动条函数cv2.createTrackerbar()的使用
- 2024-10-24 【创新办公】J5create虫洞交换器实现双设备无缝连接。
- 2024-10-24 十铨发布T-CREATE雷电3外接式固态硬盘,以及T-FORCE CARDEA Z44L SSD
- 2024-10-24 j5create USB 3.0跨平台传输线,让两台设备传输文件更方便
- 2024-10-24 C#常见错误_调用第三方动态库dll(c#调用c动态库)
- 2024-10-24 百万Java 面试题整理(1.0)(100个java面试题及答案)
- 2024-10-24 windows11 上无法在vs2019上执行powershell脚本的解决方案
- 2024-10-24 opencv实时识别指定物体(opencv实现图像识别)
- 2024-10-24 全程软件测试(六十六):软件测试之MySQL基础—读书笔记
- 2024-10-24 c++内存泄漏解决方案(c++内存泄漏的原因)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- css导航条 (66)
- sqlinsert (63)
- js提交表单 (60)
- param (62)
- parentelement (65)
- jquery分享 (62)
- check约束 (64)
- curl_init (68)
- sql if语句 (69)
- import (66)
- chmod文件夹 (71)
- clearinterval (71)
- pythonrange (62)
- 数组长度 (61)
- javafx (59)
- 全局消息钩子 (64)
- sort排序 (62)
- jdbc (69)
- php网页源码 (59)
- assert h (69)
- httpclientjar (60)
- postgresql conf (59)
- winform开发 (59)
- mysql数字类型 (71)
- drawimage (61)
本文暂时没有评论,来添加一个吧(●'◡'●)