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

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

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

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位。






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值