【2021.01.06】内存映射文件
什么是内存映射文件?好处:免去了打开文件关闭文件等等操作,想操作时直接操作自身的虚拟内存即可。当要读写的文件特别大的时候,内存映射文件可以提供远比IO读写文件更好的性能。内存映射文件#include <iostream>#include <Windows.h>#define MAPPINGNAME L"共享文件"HANDLE g_hMapFile;LPTSTR g_lpBu
·
什么是内存映射文件?

好处:
- 免去了打开文件关闭文件等等操作,想操作时直接操作自身的虚拟内存即可。
- 当要读写的文件特别大的时候,内存映射文件可以提供远比IO读写文件更好的性能。
内存映射文件
#include <iostream>
#include <Windows.h>
#define MAPPINGNAME L"共享文件"
HANDLE g_hMapFile;
LPTSTR g_lpBuff;
DWORD MappingFile(LPCWSTR lpcFile)
{
HANDLE hFile;
HANDLE hMapFile;
DWORD dwFileMapSize;
LPVOID lpAddr;
//得到文件句柄
hFile = CreateFile(lpcFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "失败" << std::endl;
return FALSE;
}
//创建FileMapping对象
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, MAPPINGNAME);
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping 失败" << std::endl;
CloseHandle(hFile);
return FALSE;
}
//映射到虚拟内存
lpAddr = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpAddr == NULL)
{
std::cout << "MapViewOfFile 失败" << std::endl;
CloseHandle(hMapFile);
CloseHandle(hFile);
return FALSE;
}
//读取文件
DWORD dwTest1 = *(PDWORD)lpAddr;
DWORD dwTest2 = *((PDWORD)lpAddr + 0x20);
printf("dwTest1:%X dwTest2:%X\n", dwTest1, dwTest2);
//写文件
*(PDWORD)lpAddr = 0x41414141;
printf("写入:%X\n", *(PDWORD)lpAddr);
//强制更新缓存 立即显示
//默认为了效率不会立即显示 所以如果需要立即显示 使用该API即可
FlushViewOfFile(((PDWORD)lpAddr), 4);
//关闭
UnmapViewOfFile(lpAddr);
CloseHandle(hMapFile);
CloseHandle(hFile);
return TRUE;
}
int main()
{
MappingFile(L"D:\\1.txt");
return 0;
}

多进程内存映射文件

- 通过上面的代码创建对象以后就没有必要再创建了,直接打开即可(OpenFileMapping),需要注意名称一致(#define MAPPINGNAME L"共享文件")。
- 其次映射到虚拟内存(MapViewOfFile)。
- 读取数据或修改数据。
- 最后释放。
- 每个程序用到的DLL(无论是kernel32.dll、user32.dll还是ntdll.dll),本质上在物理内存中都只有一份。
- 操作系统不会为每个进程单独分配内存,只不过是每个进程各自映射了一份。
FILE_MAP_COPY 写拷贝
A进程和B进程,如果A进程修改的时候,会复制一份新的物理页,让A进程修改,而B进程不会受到影响。
例如:
- 在kernel32.dll中某个函数头下了一个断点,字节被修改为0xCC,但是其他进程并不受影响。
- 当资源释放时,不会写回到文件里,真正写回去的还是原来的物理内存,而不是被复制的那一份物理内存。
更多推荐



所有评论(0)