虚拟内存——Windows核心编程学习手札之十四
虛擬內存
——Windows核心編程學習手札之十四
系統信息
有些操作系統的值是根據主機而定的,如頁面大小、分配粒度大小等,這些值不用硬編碼形式,進程初始化時應檢索這些值以使用。函數GetSystemInfo函數用于檢索與主機相關的值:
VOID GetSystemInfo(LPSYSTEM_INFO psinf);
傳遞SYSTEM_INFO結構的地址,該函數將初始化結構成員并返回。
typedef struct _SYSTEM_INFO{
?????? union{
???????????????????? DWORD dwOemId;//obsolete,do not use
???????????????????? Struct{
?????????????????????????????????? WORD wProcessorArchitecture;//用于指明處理結構,如Intel、Alpha、???????????????????????????????????????? ?????? Intel64位lpha64位,主要在windows2000中;
?????????????????????????????????? WORD wReserved;
???????????????????? };
?????? };
?????? DWORD dwPageSize;//用于顯示CPU頁面大小,如x86是4096字節;Alpha是8192字節;IA-64是8192字節;
?????? LPVOID lpMinimumApplicationAddress;//用于給出每個進程的可用地址空間的最小內存地址,如Windows98中是4 194 304或0x00400000,因為每個進程的地址空間中下面4MB是不能使用的,用戶方式的分區在該地址之上;如windows2000中,這個值是65 536或0x000100000,因為每個進程的地址空間中開頭的64KB是空閑的;
?????? LPVOID lpMaximumApplicationAddress;//用戶給出每個進程的可用地址空間的最大內存地址,如windows98,這個地址是2 147 483 647或0x7FFFFFFF,因為共享內存映射文件和共享操作系統代碼包含在上面的2GB分區中;如windows2000,這個地址是內核方式內存開始的地址,不足64KB;
?????? DWORD_PTR dwActiveProcessorMask;//一個位屏蔽,用于指明哪個CPU是活動的;
?????? DWORD dwNumberOfProcessors;//用于指明計算機中的CPU數目;
?????? DWORD dwProcessorType;//用于指明處理器類型,如Intel386、486/Pentium,主要在windows98中;
?????? DWORD dwAllocationGranularity;//顯示保留的地址空間區域的分配粒度,目前,所有windows平臺都是65 356;
?????? WORD wProcessorLevel;//用于進一步細分處理器的結構,如設定Intel Pentium Pro或Pentium Ⅱ,主要用于windows2000;
?????? WORD wProcessorRevision;//用于進一步細分處理器的級別,用于windows2000;
}SYSTEM_INFO,*LPSYSTEM_INFO;
對既定的系統,這些值都是相同的,不需要在既定的進程中多次調用函數,通過GetSystemInfo函數應該程序可以查詢關于系統中的這些值。
示例代碼:
#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
?
?
void ShowCPUInfo(WORD wProcessorArchitecture,WORD wProcessorLevel,WORD wProcessorRevision)
{
?????? TCHAR strInfo[256];
?????? memset(strInfo,0,256);
?????? /*PROCESSOR_ARCHITECTURE_INTEL
?????? PROCESSOR_ARCHITECTURE_MIPS
?????? PROCESSOR_ARCHITECTURE_UNKNOWN
?????? PROCESSOR_ARCHITECTURE_SHX
?????? PROCESSOR_ARCHITECTURE_ARM */
?????? switch(wProcessorArchitecture)
?????? {
?????? case PROCESSOR_ARCHITECTURE_INTEL:
????????????? if(wProcessorLevel==4)
????????????? {
???????????????????? ?wsprintf(strInfo,_T("處理器類型: Intel 80486"));
????????????? }
????????????? else if(wProcessorLevel==5)
????????????? {
???????????????????? ?wsprintf(strInfo,_T("處理器類型: Pentium"));
????????????? }
????????????? else
????????????? {
???????????????????? ?wsprintf(strInfo,_T("處理器類型: PROCESSOR_ARCHITECTURE_INTEL"));
????????????? }
?????? ??? break;
?????? case PROCESSOR_ARCHITECTURE_MIPS:
????????????? switch(wProcessorLevel)
????????????? ?{
????????????? case 3:
???????????????????? ?wsprintf(strInfo,_T("處理器類型: MIPS R3000"));
???????????????????? ?break;
?????? ??? case 4:
???????????? wsprintf(strInfo,_T("處理器類型: MIPS R4000"));
???????????? break;
??????? case 5:
???????????? wsprintf(strInfo,_T("處理器類型: MIPS R5000"));
???????????? break;
??????? default:
???????????? wsprintf(strInfo,_T("處理器類型: PROCESSOR_ARCHITECTURE_MIPS"));
???????????? break;
????????????? }
??????? break;
??? case PROCESSOR_ARCHITECTURE_SHX:
?????? ??? wsprintf(strInfo,_T("處理器類型: PROCESSOR_ARCHITECTURE_SHX"));
??????? break;
??? case PROCESSOR_ARCHITECTURE_ARM:
?????? ??? if(wProcessorLevel==4)
????????????? {
???????????? wsprintf(strInfo,_T("處理器類型: ARM version 4"));
????????????? }
??????? else
????????????? {
???????????? wsprintf(strInfo,_T("處理器類型: PROCESSOR_ARCHITECTURE_ARM"));
????????????? }
??????? break;
??? default:
??????? wsprintf(strInfo,_T("處理器類型: PROCESSOR_ARCHITECTURE_UNKNOWN"));
??????? break;
?????? }
}
?
int main(int argc, char* argv[])
{
?????? SYSTEM_INFO sinf;
?????? GetSystemInfo(&sinf);
?
?????? ShowCPUInfo(sinf.wProcessorArchitecture,sinf.wProcessorLevel,sinf.wProcessorRevision);
??????
?????? TCHAR szBuf[256];
?????? wsprintf(szBuf,_T("頁面文件大小: %d 或 0x%08x"),sinf.dwPageSize,sinf.dwPageSize);
??? wsprintf(szBuf,_T("進程的最小內存地址: %d 或 0x%08x"),sinf.lpMinimumApplicationAddress,sinf.lpMinimumApplicationAddress);
??? wsprintf(szBuf,_T("進程的最大內存地址: %d 或 0x%08x"),sinf.lpMaximumApplicationAddress,sinf.lpMaximumApplicationAddress);
??? wsprintf(szBuf,_T("當前活動的CPU: %d"),sinf.dwActiveProcessorMask);
?????? return 0;
}
虛擬內存的狀態
Windows函數GlobalMemoryStatus可用于檢索關于當前內存狀態的動態信息:
VOID GlobalMemoryStatus(LPMEMORYSTATUS pmst);
當調用GlobalMemoryStatus時,要傳遞MEMORYSTATUS結構的地址:
typedef struct _MEMORYSTATUS{
?????? DWORD dwLength;
?????? DWORD dwMemoryLoad;
?????? SIZE_T dwTotalPhys;
?????? SIZE_T dwAvailPhys;
SIZE_T dwTotalPageFile;
SIZE_T dwAvailPageFile;
SIZE_T dwTotalVirtual;
SIZE_T dwAvailVirtual;
}MEMORYSTATUS,*LPMEMORYSTATUS;
調用GlobalMemoryStatus函數之前,將dwLength成員初始化為用字節表示的結構的大小,即一個MEMORYSTATUS結構的大小。
如應用程序在內存大于4GB的計算機上運行,或者合計交換文件的大小大于4GB,可用新的GlobalMemoryStatusEx函數:
BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX pmst);
函數傳遞新的結構MEMORYSTATUSEX:
typedef struct _MEMORYSTATUSEX{
?????? DWORD dwLength;
?????? DWORD dwMemoryLoad;
?????? DWORDLONG ullTotalPhys;
?????? DWORDLONG ullAvailPhys;
DWORDLONG ullTotalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
}MEMORYSTATUSEX,*LPMEMORYSTATUSEX;
新結構和原來的MEMORYSTATUS基本相同,差別在于新結構的所有成員的大小都是64位寬,因此它的值可以大于4GB,最后一個成員ullAvailExtendedVirtual,用于指明在調用進程的虛擬地址空間的極大內存(VLM)部分中未保留內存的大小。該VLM部分只適用于某些配置中的某些CPU結構。
Windows提供了一個函數,可以用來查詢地址空間中內存地址的某些信息(如大小,存儲器類型和保護屬性等)。函數VirtualQuery:
DWORD VirtualQuery(
?????????????????? LPCVOID pvAddress,
?????????????????? PMEMORY_BASIC_INFORMATION pmbi,
?????????????????? DWORD dwLength);
Windows也提供了VirualQueryEx函數,用于使一個進程能夠查詢另一個進程的內存信息:
DWORD VirtualQueryEx(
???????????????????? HANDLE hProcess,
??????????????????? ?LPCVOID pvAddress,
???????????????????? PMEMORY_BASIC_INFORMATION pmbi,
???????????????????? DWORD dwLength);
結構體MEMORY_BASIC_INFORMATION在WinNT.h中定義:
typedef struct _MEMORY_BASIC_INFORMATION{
??????????????????????????? PVOID BaseAddress;
??????????????????????????? PVOID AllocationBase;
??????????????????????????? PVOID AllocationProtect;
??????????????????????????? SIZE_T RegionSize;
??????????????????????????? DWORD State;
??????????????????????????? DWORD Protect;
??????????????????????????? DWORD Type;
??????????? } MEMORY_BASIC_INFORMATION,* PMEMORY_BASIC_INFORMATION;
函數VirtualQuery的最后一個參數是dwLength,用于設定MEMORY_BASIC_INFORMATION結構的大小。VirtualQuery(Ex)函數返回拷貝到緩存中的字節的數量。根據pvAddress參數中傳遞的地址,VirtualQuery(Ex)函數將關于共享相同狀態、保護屬性和類型的相鄰頁面的范圍信息填入MEMORY_BASIC_INFORMATION結構中。
?
總結
以上是生活随笔為你收集整理的虚拟内存——Windows核心编程学习手札之十四的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅析IPDCC的地理信息识别和服务
- 下一篇: 在应用程序中使用虚拟内存——Window