Win3内存管理之私有内存跟共享内存的申请与释放
时间:2022-03-18 10:35
Win3内存管理之私有内存跟共享内存的申请与释放
一丶内存简介私有内存申请
通过上一篇文章.我们理解了虚拟内存与物理内存的区别. 那么我们有API事专门申请虚拟内存与物理内存的.
有私有内存跟共享内存. 私有内存的意思就是这块内存申请只在本进程的物理页当中. 共享内存就是这个物理页 A B两个进程都可以使用.
私有内存申请API
VirtualAlloc / virtualAllocEx
LPVOID VirtualAlloc(
LPVOID lpAddress, 你要申请的地址.可以指定地址.但是物理页我们不知道那个地址是否存在.所以一般为0 SIZE_T dwSize, 申请内存的大小.一般为一个页.虽然MSDN说了一Byte(字节) 为主. 但是我们知道物理内存是一个页.所以申请一个页即可. DWORD flAllocationType, 申请内存的类型. 是这样的.我们申请内存在物理页. 可以有两种类型.一种类型就是物理内存直接申请.一种就是物理内存占位置.并不申请.一般用第一种. DWORD flProtect 内存的状态.我们申请的内存状态是可读的 还是可写的. 还是可读写的.
virtualAllocEx 是远程内存申请.就是说我们可以通过指定的进程. 给这个指定进程申请内存.
new malloc的区别. 请注意.真正申请内存的其实是API. 而new malloc 是申请堆内存. 意思就是说. new malloc其实就是在已申请的内存上面划分出来了一块虚拟内存给你使用.
不管你使用没使用. 而且new关键字本质也就是malloc 只不过可以进行构造. 而 malloc的底层是通过 HeapAlloc申请的. 并没有进0环(内核)
二丶共享内存申请
1.共享内存申请
共享内存其实就是物理页可以共享使用了. A进程申请物理页往这个物理页填写内容. B进程就可以读取了.
我们具体的API
1. 申请物理页内存API
HANDLE CreateFileMapping( HANDLE hFile, 文件映射.申请的物理页可以跟文件相映射.如果不需要文件只申请物理页则不需要. LPSECURITY_ATTRIBUTES lpAttributes, SD安全属性,每个内核对象都需要的安全属性 DWORD flProtect, 权限.你申请的这个物理页是可读的可写的还是可读写. DWORD dwMaximumSizeHigh, 申请内存的高32位. windows为了支持64我操作系统.所以给了高低32位来保存地址. 如果是32位地址.则不需要.填0即可. DWORD dwMaximumSizeLow, 低32位,你要申请的物理页内存的大小 LPCTSTR lpName 进程共享物理页的名字.如果希望这个物理页B进程可以使用则需要给一个名字.
返回值: 返回物理页句柄索引.
有创建物理页 也有打开物理页 主要是B进程使用.
HANDLE OpenFileMapping( DWORD dwDesiredAccess, // access mode BOOL bInheritHandle, // inherit flag LPCTSTR lpName // object name);
当然如果B进程使用一样可以使用CreateFileMaping. 只不过会返回文件对象已经存在的错误.
2.线性地址(虚拟地址) 关联物理页.
上面申请了物理页.那么我们还需要将这个物理页映射到线性地址.需要的API如下.
LPVOID MapViewOfFile( HANDLE hFileMappingObject, // 物理页句柄 DWORD dwDesiredAccess, // 线性地址访问权限,注意跟物理页最好一直.或者比物理页更严格. DWORD dwFileOffsetHigh, // 映射线性地址的偏移位置 高32位 DWORD dwFileOffsetLow, // 低32位 SIZE_T dwNumberOfBytesToMap // 内存映射结束位置;
3.取消关联
BOOL UnmapViewOfFile( LPCVOID lpBaseAddress // starting address); 虚拟地址
关闭物理页映射则使用CloseHandle. PS: 知识 引用计数-1. 为0了则会关闭.
具体代码如下.
A进程B进程一样. A进程写入. B进程写入.
// A.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> int main() { getchar(); //A进程 申请物理页 HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000, TEXT("共享内存")); //2.映射虚拟内存(线性地址的) LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0x1000); // A进程写内存 *(char *)lpBuf = ‘a‘; //写内存 printf("写入内存为a \r\n"); getchar(); UnmapViewOfFile(lpBuf); CloseHandle(hMap); return 0; }
B进程代码:
// A.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> int main() { getchar(); //A进程 申请物理页 HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000, TEXT("共享内存")); //2.映射虚拟内存(线性地址的) LPVOID lpBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0x1000); // A进程写内存 printf("读取内存为 %c \r\n",*(char *)lpBuf); getchar(); UnmapViewOfFile(lpBuf); CloseHandle(hMap); return 0; }
这样就实现了物理页共享.