Windows 內存管理


參考文獻:

http://blog.csdn.net/wubin1124/article/details/3760242


工作集(內存): 可以這麼理解, 此值就是該進程所佔用的總物理內存. 但是這個值是由兩部分組成, 即 '專用工作集' + '共享工作集'.

內存(專用工作集): 這對於一個進程是最重要的, 它代表了一個進程獨佔用了多少內存. 

內存(共享工作集): 這是該進程和別的進程共享的內存量. 通常, 這是加載一個 dll 所佔用的內存. 

提交大小: 屬於 Committed 那一類. 但是不一定在物理內存中, 有些可能位於交換文件中. 如果有一個程序, 原本佔 500MB 內存, 但是絕大多數內存都不使用, 則可以通過 `EmptyWorkingSet` 向操作系統發送請求, 將此進程的不常用的內容從物理內存中換出到換頁文件中保存, 如下圖:





寫在最後


0. 工作集, 即在物理內存中的數據的集合.

1. 工作集 = 專用 + 共享

2. 將所有的 "工作集" 相加後的值會大於任務管理器中內存佔用的百分比, 因爲百分比對共享內存進行排重了.

3. "提交大小" 和 "工作集" 是兩個層面的概念, 大部分活躍進程的 "工作集" 會大於 "提交大小", 而大部分非活躍的進程 "工作集" 會小於 "提交大小", 但是兩者沒有絕對關係.

4. 虛擬內存: 就是換頁文件.



分頁文件:硬盤上一個或者多個隱藏文件pagefile.sysWindows用於存儲未存入內存的部分程序和數據文件。頁面文件和物理內存或隨機存取內存(RAM)構成了虛擬內存。Windows會根據需要將數據從頁面文件移至內存,或將數據從內存移至頁面文件以便爲新數據釋放內存。也叫“交換文件”。


Windows使用工具集:

Sysinternals Suite

https://technet.microsoft.com/zh-cn/library/bb842062.aspx


分頁和非分頁內存
Windows規定有些虛擬內存頁面是可以交換到磁盤的文件中的,這類內存被稱爲分頁內存,而有些虛擬內存是不能被交換到磁盤的文件中,這些內存被稱爲非分頁內存。當程序的中斷請求在DISPATCH_LEVEL之上時,包括DISPATCH_LEVEL,程序只能使用非分頁內存。

// WindbgCmdTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib,"Psapi.lib")
#include <Psapi.h>

#define  MEM_M (1024*1024)
void OutputSystemMem(MEMORYSTATUS New, MEMORYSTATUS Old)
{
	//cout<<"減少物理內存="<<(New.dwAvailPhys-Old.dwAvailPhys)/MEM_M<<endl;
	//cout<<"減少可用頁文件="<<(New.dwAvailPageFile-Old.dwAvailPageFile)/MEM_M<<endl;
	//cout<<"減少可用進程空間="<<(New.dwAvailVirtual-Old.dwAvailVirtual)/MEM_M<<endl;
}


static PROCESS_MEMORY_COUNTERS stLastMem;


void OutputProcessMem()
{
	PROCESS_MEMORY_COUNTERS pro;
	HANDLE handle = GetCurrentProcess();
	GetProcessMemoryInfo(handle, &pro, sizeof(pro));
	cout<<"缺頁中斷次數	"<<"new("<<pro.PageFaultCount/MEM_M<<") "<<"old("<<stLastMem.PageFaultCount/MEM_M<<")"<<endl;
	cout<<"使用內存高峯	"<<"new("<<pro.PeakWorkingSetSize/MEM_M<<") "<<"old("<<stLastMem.PeakWorkingSetSize/MEM_M<<")"<<endl;
	cout<<"當前使用的內存	"<<"new("<<pro.WorkingSetSize/MEM_M<<") "<<"old("<<stLastMem.WorkingSetSize/MEM_M<<")"<<endl;
	cout<<"使用頁面緩存池高峯	"<<"new("<<pro.QuotaPeakPagedPoolUsage/MEM_M<<") "<<"old("<<stLastMem.QuotaPeakPagedPoolUsage/MEM_M<<")"<<endl;
	cout<<"使用頁面緩存池	"<<"new("<<pro.QuotaPagedPoolUsage/MEM_M<<") "<<"old("<<stLastMem.QuotaPagedPoolUsage/MEM_M<<")"<<endl;
	cout<<"使用非分頁緩存池高峯	"<<"new("<<pro.QuotaPeakNonPagedPoolUsage/MEM_M<<") "<<"old("<<stLastMem.QuotaPeakNonPagedPoolUsage/MEM_M<<")"<<endl;
	cout<<"使用非分頁緩存池	"<<"new("<<pro.QuotaNonPagedPoolUsage/MEM_M<<") "<<"old("<<stLastMem.QuotaNonPagedPoolUsage/MEM_M<<")"<<endl;
	cout<<"使用分頁文件(提交的內存文件大小)	"<<"new("<<pro.PagefileUsage/MEM_M<<") "<<"old("<<stLastMem.PagefileUsage/MEM_M<<")"<<endl;
	cout<<"使用分頁文件高峯	"<<"new("<<pro.PeakPagefileUsage/MEM_M<<") "<<"old("<<stLastMem.PeakPagefileUsage/MEM_M<<")"<<endl;
	cout<<endl;
	memcpy(&stLastMem,&pro,sizeof(pro));
}
#define  VIRTUAL_ALLOC_TEST_SIZE 10*MEM_M
int _tmain(int argc, _TCHAR* argv[])
{
	memset(&stLastMem,0,sizeof(stLastMem));
	OutputProcessMem();

	MEMORYSTATUS memStatusVirtual;
	GlobalMemoryStatus(&memStatusVirtual);

	LPVOID pV=VirtualAlloc(NULL,VIRTUAL_ALLOC_TEST_SIZE,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE);
	if(pV==NULL)
	{
		cout<<"沒有那麼多虛擬空間!"<<endl;
	}
	MEMORYSTATUS memStatusVirtual1;
	GlobalMemoryStatus(&memStatusVirtual1);
	cout<<"VirtualAlloc(NULL,1000*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READWRITE);"<<endl;
	OutputSystemMem(memStatusVirtual1,memStatusVirtual);
	OutputProcessMem();


	cout<<"\n";
	pV=VirtualAlloc(pV,VIRTUAL_ALLOC_TEST_SIZE,MEM_COMMIT,PAGE_READWRITE);
	if (pV == NULL)
	{
		DWORD eLastError = GetLastError();
		cout <<"eLastError: %d" << eLastError;
	}
	MEMORYSTATUS memStatusVirtual2;
	GlobalMemoryStatus(&memStatusVirtual2);
	cout<<"VirtualAlloc(pV,10*1024*1024,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);"<<endl;
	OutputSystemMem(memStatusVirtual2,memStatusVirtual1);
	OutputProcessMem();


	char * pC = (char *)pV;
	cout<<"\n";
	cout<<"pC[VIRTUAL_ALLOC_TEST_SIZE-1] = 0;;"<<endl;
	pC[VIRTUAL_ALLOC_TEST_SIZE-1] = 0;
	OutputProcessMem();


	cout<<"\n";
	char * p = new char[10*MEM_M];
	MEMORYSTATUS memStatusVirtual8;
	GlobalMemoryStatus(&memStatusVirtual8);
	cout<<"char * p = new char[10*MEM_M];"<<endl;
	OutputSystemMem(memStatusVirtual8,memStatusVirtual2);

	OutputProcessMem();


	cout<<"\n";
	VirtualFree(pV,VIRTUAL_ALLOC_TEST_SIZE,MEM_DECOMMIT);
	MEMORYSTATUS memStatusVirtual3;
	GlobalMemoryStatus(&memStatusVirtual3);
	cout<<"	VirtualFree(pV,10*1024*1024,MEM_DECOMMIT);"<<endl;
	OutputSystemMem(memStatusVirtual3,memStatusVirtual2);
	OutputProcessMem();

	cout<<"\n";
	VirtualFree(pV,VIRTUAL_ALLOC_TEST_SIZE,MEM_RELEASE);
	MEMORYSTATUS memStatusVirtual4;
	GlobalMemoryStatus(&memStatusVirtual4);
	cout<<"VirtualFree(pV,10*1024*1024,MEM_RELEASE);"<<endl;
	OutputSystemMem(memStatusVirtual4,memStatusVirtual3);
	OutputProcessMem();

	cout<<"\n";
	VirtualUnlock(pV,VIRTUAL_ALLOC_TEST_SIZE);
	MEMORYSTATUS memStatusVirtual5;
	GlobalMemoryStatus(&memStatusVirtual5);
	cout<<"VirtualUnlock(pV,10*1024*1024);"<<endl;
	OutputSystemMem(memStatusVirtual5,memStatusVirtual4);
	OutputProcessMem();


	cout<<"delete[] p;"<<endl;
	delete[] p;
	OutputProcessMem();

	getchar();
	return 0;
}



發佈了72 篇原創文章 · 獲贊 6 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章