1. 程式人生 > >Windows虛擬記憶體的使用(五)

Windows虛擬記憶體的使用(五)



VirtualQuery的使用

VirtualQuery函式可以查詢本程序地址空間中記憶體區域的詳細情況(區域大小,區域內容等資訊)
函式原型:DWORD VirtualQuery(LPVOID lpAddress,PMEMORY_BASIC_INFORMATION lpBuffer,DWORD dwLength);
lpAddress:表示要查詢狀態的記憶體區域開始地址
lpBuffer:一個用於返回的結構資料的緩衝
dwLength:是緩衝的長度
使用VirtualQueryEx函式可以查詢指定程序的地址空間情況,原型:SIZE_T WINAPI VirtualQueryEx(HANDLE hProcess,LPVOID lpAddress,PMEMORY_BASIC_INFORMATION lpBuffer,DWORD dwLength);
hProcess:待查詢其地址空間的程序控制代碼。
用此函式無法查詢核心分割槽情況,只能查詢使用者分割槽的記憶體使用情況。

/************************************************************************/
/* 
程式說明:VirtualQuery的使用,通過VirtualQuery輸出記憶體資訊
日期    :2014/12/30
*/
/************************************************************************/

#include "stdafx.h"
#include <windows.h>
#include <atlstr.h>

/************************************************************************/
/* 
功能:把記憶體資訊結構體資訊格式化輸出。
引數:mi:記憶體資訊結構體
返回:格式化字串
*/
/************************************************************************/
CString FormatMemInfo(MEMORY_BASIC_INFORMATION &mi)
{
	CString strAllocProtect;
	//記憶體區域初始化時的保護方式
	if(mi.AllocationProtect & PAGE_NOACCESS)                // 0x0001
	{
		strAllocProtect = _T("N  ");
	}
	if(mi.AllocationProtect & PAGE_READONLY)                // 0x0002
	{
		strAllocProtect = _T("R  ");
	}
	else if(mi.AllocationProtect & PAGE_READWRITE)          // 0x0004
	{
		strAllocProtect = _T("RW ");
	}
	else if(mi.AllocationProtect & PAGE_WRITECOPY)          // 0x0008
	{
		strAllocProtect = _T("WC ");
	}
	else if(mi.AllocationProtect & PAGE_EXECUTE)            // 0x0010
	{
		strAllocProtect = _T("E  ");
	}
	else if(mi.AllocationProtect & PAGE_EXECUTE_READ)       // 0x0020
	{
		strAllocProtect = _T("ER ");
	}
	else if(mi.AllocationProtect & PAGE_EXECUTE_READWRITE)  // 0x0040
	{
		strAllocProtect = _T("ERW");
	}
	else if(mi.AllocationProtect & PAGE_EXECUTE_WRITECOPY)  // 0x0080
	{
		strAllocProtect = _T("EWC");
	}
	if(mi.AllocationProtect & PAGE_GUARD)                   // 0x0100
	{
		strAllocProtect += _T("+Guard");
	}
	if(mi.AllocationProtect & PAGE_NOCACHE)                 // 0x0200
	{
		strAllocProtect += _T("+NoCache");
	}
	//記憶體頁的狀態
	CString strState;
	if(mi.State == MEM_COMMIT)
	{
		strState = _T("Commit ");
	}
	else if(mi.State == MEM_FREE)
	{
		strState = _T("Free   ");
	}
	else if(mi.State == MEM_RESERVE)
	{
		strState =_T( "Reserve");
	}
	else
	{
		strState =_T( "Damned ");
	}
	//記憶體頁的當前保護屬性
	CString strProtect;
	if(mi.Protect & PAGE_NOACCESS)
	{
		strProtect = _T("N  ");
	}
	else if(mi.Protect & PAGE_READONLY)
	{
		strProtect = _T("R  ");
	}
	else if(mi.Protect & PAGE_READWRITE)
	{
		strProtect = _T("RW ");
	}
	else if(mi.Protect & PAGE_WRITECOPY)
	{
		strProtect = _T("WC ");
	}
	else if(mi.Protect & PAGE_EXECUTE)
	{
		strProtect = _T("E  ");
	}
	else if(mi.Protect & PAGE_EXECUTE_READ)
	{
		strProtect = _T("ER ");
	}
	else if(mi.Protect & PAGE_EXECUTE_READWRITE)
	{
		strProtect = _T("ERW");
	}
	else if(mi.Protect & PAGE_EXECUTE_WRITECOPY)
	{
		strProtect = _T("EWC");
	}
	else if(mi.Protect & PAGE_GUARD) 
	{
		strProtect += _T("+Guard");
	}
	else if( mi.Protect & PAGE_NOCACHE )
	{
		strProtect += _T("+NoCache");
	}
	//記憶體頁型別
	CString strType;
	if(mi.Type == MEM_IMAGE)
	{
		strType =_T( "Image  ");
	}
	else if(mi.Type == MEM_MAPPED)
	{
		strType = _T("Mapped ");
	}
	else if(mi.Type == MEM_PRIVATE)
	{
		strType = _T("Private");
	}
	else
	{
		strType = _T("-      ");
	}

	CString strRet;
	strRet.Format(_T("%8X  %8X	%8X	%8uKB %5s  %7s %5s %7s"), mi.BaseAddress, mi.AllocationBase
		, (DWORD)mi.AllocationBase + (DWORD)mi.RegionSize
		, (DWORD)mi.RegionSize/1024
		, strAllocProtect, strState, strProtect, strType);

	return strRet;
}

int _tmain(int argc, _TCHAR* argv[])
{
	SYSTEM_INFO info;
	//獲取系統資訊
	GetSystemInfo(&info);
	//最小的記憶體地址和最大的記憶體地址
	void * pLowerBound = (void*)info.lpMinimumApplicationAddress;
	void * pUpperBound = (void*)info.lpMaximumApplicationAddress;

	MEMORY_BASIC_INFORMATION mi;
	void* pPtr = pLowerBound;
	void* pOldPtr = pPtr;

	_putts(_T("BaseAddress AllocBase   EndAddress		Size  AllocProtect State	CurProtect	TYPE"));
	while (pPtr <= pUpperBound)
	{
		//查詢自己程序中的虛擬記憶體頁的資訊
		if (VirtualQuery(pPtr,&mi,sizeof(mi)) == 0)
		{
			break;
		}
		_putts(FormatMemInfo(mi));
		pOldPtr = pPtr;
		pPtr = (BYTE*)mi.BaseAddress+mi.RegionSize;
		if (pPtr <= pOldPtr)
		{
			break;
		}
	}
	_tsystem(_T("pause"));
	return 0;
}

Windows堆管理器的使用:
1 與虛擬記憶體管理不同,Windows為小塊記憶體的管理提供了Windows堆管理器。
2 Windows堆管理器內部在底層依然呼叫了虛擬記憶體管理。
3 Windows堆屬於程序,程序內的所有執行緒都可以訪問該程序中所有的堆。
4 Windows為每個程序在準備啟動時都預設建立了一個堆,使用GetProcessHeap函式可以得到這個預設堆的控制代碼。

WIndows堆API的使用:
1 因為堆API與C/C++堆管理方式類同,因此可以使用這組堆API直接代替C/C++的堆管理函式或運算子。
2 windows堆API的效能僅次於虛擬記憶體管理,但是高於任何其他堆管理函式。
3 因為依託於虛擬記憶體管理,所以可以使用windows堆函式分配想要的任意尺寸的記憶體塊。
4 使用HeapSize可以快速的得到某塊已分配記憶體的原始分配大小,方便校驗和限定對記憶體的訪問。
5 使用HeapValidate可以校驗一個對記憶體的完整性,從而提早發現野指標等問題
6 使用heapWalk可以遍歷堆,從而有機會檢測到記憶體洩漏的問題。

程式碼如下:

/************************************************************************/
/* 
程式的使用:堆的使用
日期      :2014/12/30
*/
/************************************************************************/

#include "stdafx.h"
#include <windows.h>
#include <time.h>

int _tmain(int argc, _TCHAR* argv[])
{
	srand((unsigned int)time(NULL));
	//使用預設堆
	HANDLE hHeap = GetProcessHeap();

	const int iCnt = 1000;
	float* fArray = (float*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iCnt * sizeof(float));
	for (int i = 0; i < iCnt; i++)
	{
		fArray[i] = 1.0f * rand();
	}
	fArray = (float*)HeapReAlloc(hHeap,HEAP_ZERO_MEMORY,fArray,2 * iCnt * sizeof(float));
	for (int i = iCnt; i < 2 * iCnt; i++)
	{
		fArray[i] = 1.0f * rand();
	}
	HeapFree(hHeap,0,fArray);

	//使用私有堆
	hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS,0,0);
	fArray = (float*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iCnt * sizeof(float));
	for (int i = 0; i < iCnt; i++)
	{
		fArray[i] = 1.0f * rand();
	}
	fArray = (float*)HeapReAlloc(hHeap,HEAP_ZERO_MEMORY,fArray,2 * iCnt * sizeof(float));
	for (int i = iCnt; i < 2 * iCnt; i++)
	{
		fArray[i] = 1.0f * rand();
	}
	HeapFree(hHeap,0,fArray);
	HeapDestroy(hHeap);
	return 0;
}

相關推薦

初始化Windows虛擬KVM的網卡IP

KVM windows 網卡配置 新創建的Windows虛擬機如果不能通過DHCP獲取IP,我們就需要登錄到虛擬機內手動配置,很麻煩。這個工作能自動化最好,為Windows虛擬機進行初始化通常有兩種思路:1. 通過cloudbase-init,這個是cloud-init的

Java虛擬Java的四種引用級別

tsp 進行 tro 圖片 分享 ros 通過 技術 存在 1.前言   HotSpot采取了可達性分析算法用來判斷對象是否被能被GC,無論是引用計算法還是可達性分析算法都是判斷對象是否存在引用來判斷對象是否存活。如果reference類型的數據中存儲的數值代表的是另外一塊

深入拆解虛擬機器JVM是如何執行方法呼叫的?

虛方法呼叫 (1)Java中所有非私有例項方法呼叫都會被 編譯成invokevirtual指令,而介面方法呼叫會被編譯成invokevirtualface指令。這兩種指令,均屬於Java虛擬機器中的虛方法呼叫 (2)Java虛擬機器採用了一種用空間換時間的策略實現動態繫結。它為每個方

Linux虛擬記憶體swap調優篇-swappiness引數

                     Linux虛擬記憶體(swap)調優篇                                            作者:尹正傑 版權宣告:原創作品,謝絕轉載!否則將追究法律責任。     swappiness的值的大小對如何使用swap分

Windows網路程式設計:多執行緒訊息處理

對於服務端來說,呼叫accept()函式同意客戶端連線的請求後,需要處理完與這個客戶端的通訊後回到accept()繼續等待下一個客戶端的連線,如果一個客戶端請求連線時服務端並沒有在accept()處等待,客戶端是無法成功連上服務端的,因此併發客戶端連線的服務端必然是多執行緒的。 服務

JAVA虛擬機器垃圾收集器與物件分配和回收策略

可達性分析演算法的效率 可達性分析中從GC Roots節點找引用鏈,可作為GC Roots的節點主要在全域性性的引用(常量或類靜態屬性)與執行上下文(棧幀中的本地變量表),如果要逐個檢查,必然會消耗很多時間。 另外,可達性分析對執行時間的敏感還體現在GC停頓上,

Java程式設計師從笨鳥到菜鳥之九十六深入java虛擬機器——java本地介面JNI詳解

        對於java程式設計師來說,java語言的好處和優點,我想不用我說了,大家自然會說出很多一套套的。但雖然我們作為java程式設計師,但我們不得不承認java語言也有一些它本身的缺點。比如在效能、和底層打交道方面都有它的缺點。所以java就提供了一些本地介面,他主要的作用就是提供一個標準的方式讓

Windows執行緒關鍵段無法解決執行緒同步問題

關鍵段: 關鍵段型別CRITICAL_SECTION 1.初始化關鍵段: void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 2.銷燬關鍵段: void DeleleCriticalSe

如何增加Ubuntu的虛擬記憶體

今日編譯某軟體系統時,出現如下錯誤: virtual memory exhausted: Cannot allocate memory  為解決此問題,找到如下解決方案。 1、開啟終端,切換到root使用者,輸入:free -m檢視記憶體狀態 [[email pr

OpenStack之Nova分析——建立虛擬機器

上篇兩篇文章分析了Nova Scheduler服務,這篇文章我們繼續來分析建立虛擬機器的過程。先來回顧一下。 class FilterScheduler(driver.Scheduler): def scheduler_run_instance(self, cont

JAVA虛擬機器:Javac編譯原理

1、Javac編譯器的基本結構 Javac主要有4個模組:詞法分析、語法分析、語義分析、程式碼生成。 2、詞法分析 (1)功能:讀取原始檔的字元流,解析出符合Java語言規範的Token序列。 (2)關鍵類: com.sun.tools.javac.pars

android修改虛擬記憶體方法

如果有理有原始碼的話, 修改:out/target/product/xxx/system/build.prop檔案 dalvik.vm.heapstartsize=12m         --------------->應用啟動,立馬分屏12M記憶體 da

讀懂作業系統之虛擬記憶體

前言 由於個人對虛擬記憶體這塊特別感興趣,所以就直接暫且跳過其他,接下來將通過幾篇文章進行詳細講解,當然其他基礎內容後續在我進行相應整體學習後也會同步輸出文章,比如作業系統概念、程式連結、程序管理、頁面置換演算法、流水線、浮點指令、記憶體管理、磁碟管理等內容。不管周遭的環境如何,畢竟還很菜,堅持每天讓自己進步

Windows虛擬記憶體的使用

 VirtualQuery的使用 VirtualQuery函式可以查詢本程序地址空間中記憶體區域的詳細情況(區域大小,區域內容等資訊) 函式原型:DWORD VirtualQuery(LPVOID lpAddress,PMEMORY_BASIC_INFORMATION

Windows核心基礎虛擬記憶體空間佈局

32位Windows作業系統支援32位定址,因此2的32次方就等於4GB,每個程式在執行時都會被對映進4GB空間的記憶體空間,這4GB空間不全是使用者可以使用的,其中0x7fffffff-0xffffffff是2GB的核心空間,這部分用來儲存核心的資料,使用者程式是無法直接訪問的。

Java虛擬機器--非堆記憶體的引數配置

方法區配置 JDK1.6 , JDK1.7配置永久區大小: -XX:PermSize:初始的永久區大小;-XX:MaxPermSize:最大永久區; JDK1.8使用元資料區替代永久區: 預設情

Windows虛擬記憶體的使用

鎖定頁面和解鎖頁面 1 通過呼叫VirtualLock方法,可以將頁面鎖定在實體記憶體中,從而防止虛擬記憶體管理機制將頁面交換至頁面檔案,而引起不必要的硬碟和實體記憶體之間的低效頁面交換。 2 通過呼叫VirtualUnlock方法,可以解鎖頁面,允許系統對頁面進行交換操作

80386學習 80386分頁機制與虛擬記憶體

一. 頁式記憶體管理介紹   80386能夠將記憶體分為不同屬性的段,並通過段描述符、段表以及段選擇子等機制,通過段基址和段內偏移量計算出線性地址進行訪問,這一記憶體管理方式被稱為段式記憶體管理。   這裡要介紹的是另一種記憶體管理的方式:80386在開啟了分頁機制後,便能夠將實體記憶體劃分為一個個大小相同且

讀懂作業系統之虛擬記憶體頁表

前言 在一個擁有32位的地址空間,4KB的頁面(212),並且每個PTE為4個位元組,那麼頁表大小為4MB(4 * 232 / 212),但若為64位地址空間,4KB的頁面(212)且每個PTE為4位元組,那麼頁表大小為16TB(4 * 264 / 212),由於頁表常駐記憶體,佔用記憶體

菜鳥教程之工具使用——JRebel與Windows服務的Tomcat集成

-m end 個人 再見 proc key pre 安裝 target 之前寫過一篇Tomcat借助JRebel支持熱部署的文章——《借助JRebel使Tomcat支持熱部署 》。介紹的是在開發、測試環境中的配置。可是正式的部署環境。我們不會通過命令行來啟動Tomcat,