1、申請內存的兩種方式
<1>通過VirtualAlloc/VirtualAllocEx申請的:PrivateMemory(當前的線性地址獨享物理頁)
<2>通過CreateFileMapping映射的:Mapped Memory(線性地址對應的物理頁可能不是獨有的,可能與其他進程共享物理頁)
Mapped Memory可以分爲兩類,一類是共享文件,一類是共享物理頁
實驗代碼:
#include <windows.h>
#include <stdio.h>
#define MapFileName "共享內存"
int main()
{
//內核對象:1、物理頁 2、文件
HANDLE g_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUFSIZ, MapFileName);
getchar();
//將物理頁與線性地址進行映射
LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
*(PDWORD)g_lpBuff = 0x12345678;
printf("A進程寫入地址,內容%p - %x", g_lpBuff, *(PDWORD)g_lpBuff);
getchar();
return 0;
}
我們先運行程序並停下來,用WinDbg查看該進程的內存使用情況如下
我們繼續運行程序觀察如下:
所以CreateFileMapping函數並沒有影響進程的線性地址空間,MapViewOfFile纔將線性地址空間與物理內存映射上
實驗代碼二
#include <windows.h>
#include <stdio.h>
#define MapFileName "共享內存"
int main()
{
//內核對象:1、物理頁 2、文件
HANDLE g_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MapFileName);
//將物理頁與線性地址進行映射
LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
printf("B進程讀取%x", *(PDWORD)g_lpBuff);
getchar();
return 0;
}
運行進程B可以讀出A進程寫入的值,這就是所謂的共享進程,共享內存的本質就是內存映射
2、共享文件
實驗代碼
#include <windows.h>
#include <stdio.h>
#define MapFileName "共享內存"
int main()
{
HANDLE g_hFile = CreateFile("C:\\NOTEPAD.EXE", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//內核對象:1、物理頁 2、文件
HANDLE g_hMapFile = CreateFileMapping(g_hFile, NULL, PAGE_READWRITE, 0, BUFSIZ, MapFileName);
//將物理頁與線性地址進行映射
LPTSTR g_lpBuff = (LPTSTR)MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUFSIZ);
getchar();
return 0;
}
運行該程序並在WinDbg中查看內存線性地址分配情況
3、鏡像文件
HMODULE hModule = ::LoadLibrary(“C:\NOTEPAD.EXE”);
<1>LoadLibary就是通過內存映射的方式實現的
<2>爲了避免影響到別人,屬性位寫拷貝
實驗代碼
#include <windows.h>
#include <stdio.h>
int main()
{
HMODULE hModule = ::LoadLibrary("C:\\NOTEPAD.EXE");
getchar();
return 0;
}
運行時需要將NOTEPAD.EXE烤到C根目錄下