20170805Windows12_3_虚拟内存页面区块/内存信息

来源:互联网 发布:微博淘宝客发产品软件 编辑:程序博客网 时间:2024/06/05 16:57

虚拟内存页面区块/内存信息:

如何提高内存扫描的效率:

1:之前做的,都是直接扫描进程内存的前面2G内存空间,要扫描完,需要一定的时间,而且,可能扫描出来的重复数据比较多,后面,提到了先获取进程的堆块空间,然后扫描,但是实际上,这样提高效率的可能性不高,Windows的内存管理,是按照页面管理的,大部分CPU的页面大小都是64KB。
2:为了提高内存扫描的速度,需要获取Windows里面页面区域的属性,我们可以使用VirtualQueryEx这个函数来获取。
VirtualQueryEx(    _In_ HANDLE hProcess,    _In_opt_ LPCVOID lpAddress,    _Out_writes_bytes_to_(dwLength, return) PMEMORY_BASIC_INFORMATION lpBuffer,    _In_ SIZE_T dwLength    );

参数:
    1:HANDLE,制定进程的句柄,这表明其拥有查询其他进程的能力。
    2:addr:内存地址
    3:回写的参数,调用成功后,他会对lpBuffer进行填充。
    4:MEMORY_BASIC_INFORMATION的大小,size。
3:回写内容:
typedef struct _MEMORY_BASIC_INFORMATION {    PVOID BaseAddress;    PVOID AllocationBase;    DWORD AllocationProtect;    SIZE_T RegionSize;    DWORD State;    DWORD Protect;    DWORD Type;} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

内容:
    1:BaseAddress:回写的首地址,即页面的首地址
    2:RegionSize:页面的大小,从基址开始,的大小
    3:State,虚拟内存的状态:总共有三种可能的状态:MEM_COMMIT(0x1000):代表已经进行提交,MEM_FREE(0x10000):内存还未使用,MEM_RESERVE(0x2000):保留,已经有人用了,但是未加载进物理内存。
    4:Protect:page的一个操作权限,这个操作权限是作用于物理内存,虚拟内存没有这样的权限,包括读写,执行等。
    5:Type:MEM_IMAGE:印象,映射,是exe或者dll加载时候的状态,MEM_MAPPED:映射的一个区段,虚拟内存往物理内存映射的时候,存在一个区段,区目。目前还未学习到。MEM_PRIVATE:
4:获取页面属性示例:
#include <windows.h>#include <tchar.h>int main(){DWORD hProcessID = GetCurrentProcessId();HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, hProcessID);MEMORY_BASIC_INFORMATION mbi;DWORD dwAddr = 0x0;while (sizeof(mbi) == VirtualQueryEx(hProcess, (LPVOID)dwAddr, &mbi, sizeof(mbi))){_tprintf(TEXT("BaseAddr:0x%x Size:0x%x State:0x%x\r\n"), mbi.BaseAddress, mbi.RegionSize, mbi.State);dwAddr += (DWORD)mbi.RegionSize;}return 0;}


5:从上面可以看出,很多的State都是0x10000,标识其没有被使用过,排除这些未使用的内存区块,就可以大大提高内存扫描的速度。

动态获取系统内存信息:

1:所有的内存是和我们系统相关的,当需要使用的时候,虚拟内存就加载到物理内存。
2:除了前面学的页面大小,分配颗粒之外,在SystemInfo里面还存储了用户区域的开始以及结束的地址,用户区域的开始以及结束地址可以被获取出来。动态获取会使程序的收缩性变得更强。
3:
#include <iostream>#include <windows.h>#include <tchar.h>int main(){setlocale(LC_ALL, "chs");SYSTEM_INFO sysInfo;GetSystemInfo(&sysInfo);_tprintf(TEXT("页面大小:%d\r\n"), sysInfo.dwPageSize);_tprintf(TEXT("分配颗粒:%d\r\n"), sysInfo.dwAllocationGranularity);_tprintf(TEXT("用户区开始地址:0x%x\r\n"), sysInfo.lpMinimumApplicationAddress);_tprintf(TEXT("用户区最大地址:0x%x\r\n"), sysInfo.lpMaximumApplicationAddress);return 0;}

4:在32位下和64位下,我们可以发现四个数据都是一样的,在MSDN里面有说明,如果要获取64位实现同样的功能,需要调用GetNativeSystemInfo()函数。在这之前,也必须辨别当前程序是32位韩式64位。






原创粉丝点击