Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Рихтер Дж., Назар К. - Windows via C C++. Программирование на языке Visual C++ - 2009

.pdf
Скачиваний:
6264
Добавлен:
13.08.2013
Размер:
31.38 Mб
Скачать

Оглавление

 

Г Л А В А 1 4 Исследование виртуальной памяти .............................................................

460

Системная информация .........................................................................................................

460

Статус виртуальной памяти...................................................................................................

470

Управление памятью на компьютерах с архитектурой NUMA.........................................

471

Определение состояния адресного пространства ............................................................

475

Г Л А В А 1 4

Исследование виртуальной памяти

В предыдущей главе мы выяснили, как система управляет виртуальной памятью, как процесс получает свое адресное пространство и что оно собой представляет. А сейчас мы перейдем от теории к практике и рассмотрим некоторые Windowsфункции, сообщающие о состоянии системной памяти и виртуального адресного пространства в том или ином процессе.

Системная информация

Многие параметры операционной системы (размер страницы, гранулярность выделения памяти и др.) зависят от используемого в компьютере процессора. Поэтому нельзя жестко «зашивать» их значения в исходный код программ. Эту информацию надо считывать в момент инициализации процесса с помощью функ-

ции GetSystemInfo:

VOID GetSystemInfo(LPSYSTEM.INFO psi);

Вы должны передать в GetSystemInfo адрес структуры SYSTEM_WFO, и функция инициализирует элементы этой структуры:

typedef struct _SYSTEM_INFO { union {

struct {

WORD wProcessorArchitecture; WORD wReserved;

};

};

DWORD dwPageSize;

LPVOID lpMinimumApplicationAddress; LPVOID lpMaximuwApplicationAddress; DWORD_PTR dwActiveProcessorMask;

 

Глава 14. Исследование виртуальной памяти.docx 461

DWORD

dwNumberOfProcessors;

DWORD

dwProcessorType;

DWORD

dwAllocationGranularity;

WORD

wProcessorLevel;

WORD

wProcessorRevision;

} SYSTEM_INFO, *LPSYSTEM_INFO;

При загрузке система определяет значения элементов этой структуры; для конкретной системы их значения постоянны. Функция GetSystemInfo предусмотрена специально для того, чтобы и приложения могли получать эту информацию. Из всех элементов структуры лишь четыре имеют отношение к памяти. Они описаны в следующей таблице.

Табл. 14-1. Элементы структуры SYSTEM_INFO

Элемент

Описание

dwPageSize

Размер страницы памяти. На процессорах x86 это значение

 

равно 4096, а на процессорах IA-64 — 8192 байтам

lpMinimumApplicationAddress

Минимальный адрес памяти доступного адресного простран-

 

ства для каждого процесса. В Windows это значение равно 65

 

536, или 0x00010000, так как в системе резервируются лишь

 

первые 64 Кб адресного пространства каждого процесса

lpMaximumApplicationAddress

Максимальный адрес памяти доступного адресного простран-

 

ства, отведенного в «личное пользование> каждому процессу

dwAllocationGranularity

Гранулярность резервирования регионов адресного простран-

 

ства. На момент написания книги это значение составляет 64

 

Кб для всех платформ Windows.

Остальные элементы этой структуры показаны в таблице ниже.

Табл. 14-2. Элементы структуры SYSTEM_INFO, не связанные с управлением памятью

Элемент

Описание

wReserved

Зарезервирован на будущее; пока не используется

dwNumberOfProcessors

Число процессоров в компьютере. На компьютере с двухъядерным

 

процессором значение этого поля равно двум

dwActiveProcessorMask

Битовая маска, которая сообщает, какие процессоры активны (выпол-

 

няют потоки)

dwProcessorType

Устарел, больше не используется

wProcessorArchitecture

Сообщает тип архитектуры процессора, например x86, x64 или IA-64

462 Часть III. Управление памятью

Табл. 14-2. (окончание)

Элемент

Описание

wProcessorLevel

Сообщает дополнительные подробности об архитектуре процессора, на-

 

пример Intel Pentium III или Pentium IV. Вместо него для определения воз-

 

можностей процессора лучше использовать функцию IsProcessorFeature-

 

Present

wProcessorRevision

Сообщает дополнительные подробности об уровне данной архитектуры

 

процессора

Совет. Более подробную информацию об установленных на компьютере процессорах можно получить с помощью функции GetLogicalProcessorInformation, как показано на листинге ниже.

void ShowProcessors() { PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pBuffer = NULL; DWORD dwSize = 0;

DWORD procCoreCount;

B00L bResult = GetLogicalProcessorInformation(pBuffer, &dwSize); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {

_tprintf(TEXT("Impossible to get processor information\n")); return;

}

pBuffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATON)malloc(dwSize); bResult = GetLogicalProcessorInformation(pBuffer, &dwSize);

if (!bResult) { free(pBuffer);

_tprintf(TEXT("Impossible to get processor information\n")); return;

}

procCoreCount = 0;

DWORD lpiCount = dwSize / sizeof(SYSTEM_L0GICAL_PR0CESS0R_INFORMATION); for(DW0RD current = 0; current < lpiCount; current++) {

if (pBuffer[current].Relationship = RelationProcessorCore) { if (pBuffer[current].ProcessorCpre.Flags == 1) {

_tprintf(TEXT(" + one CPU core (HyperThreading)\n")); } else {

_tprintf(TEXT(" + one CPU socket\n"));

}

procCoreCount++;

}

}

Глава 14. Исследование виртуальной памяти.docx 463

_tprintf(TEXT(" -> %d active CPU(s)\n"), procCoreCount);

free(pBuffer);

}

Чтобы 32-разрядныс приложения работали в 64-разрядных версиях Windows, Майкрософт разработан уровень эмуляции под названием Windows32-bit On Windows 64-bit или WOW64. В случае 32-разрядного приложения, работающего под WOW64, возвращаемые GetSystemInfo значения могут отличаться от таковых в случае «родных» 64-разрядных приложений. Например, поле dwPageSize структуры SYSTEM_INFO на компьютере с архитектурой IA-64 в первом случае будет содержать значение 4 Кб, а во втором — 8 Кб. Чтобы выяснить, не запущена ли программа под WOW64:

BOOL IsWow64Process(

HANDLE hProcess,

PB00L pbWow64Process);

Первый параметр — это описатель нужного вам процесса, для исполняемого приложения он может быть получен вызовом GetCurrentProcess. Функция IsWow64Process обычно возвращает FALSE, если ей переданы недопустимые параметры. Если же она возвращает TRUE, булево значение, на которое указывает параметр pbWow64Process, в случае 32-разрядного приложения работающего в 32-разрядной версии Windows устанавливается в FALSE, как и в случае 64разрядиого приложения в 64-разрядной версии Windows. Это значение устанавливается в TRUE только для 32-разрядного приложения, работающего в WOW64. В этом случае нужно вызвать GetNativeSystemInfo, чтобы получить структуру SYSTEM_INFO с «родными» (а не эмулированными) значениями параметров:

void GetNativeSystemInfo( LPSYSTEM_INFO pSystemInfo);

Вместо IsWow64Process следует вызвать функцию IsOS, объявленную в файле ShlWApi.h, передав ей в качестве параметра значение OS_WOW6432. Если IsOS вернет TRUE, вызывающее 32-разрядное приложение работает под WOW64. Если же возвращается значение FALSE, вызывающе 32-разрядное приложение работает в «родной» 32-разрядной среде Windows.

Примечание. Подробнее об эмуляции 32-разрядной среды в 64-разрядных версиях Windows см. в официальной статье «Best Practices for WOW64» по ссылке http://www.microsoft.com/whdc/system/platform/64bit/WoW64_bestprac.mspx.

464 Часть III. Управление памятью

Программа-пример SysInfo

Эта программа (см. листинг SysInfo.cpp), весьма проста; она вызывает функцию GetSystemInfo и выводит на экран информацию, возвращенную в структуре SYSTEM_INFO. Файлы исходного кода и ресурсов этой программы находятся в каталоге 14-SysInfo внутри архива, доступного на веб-сайте поддержки этой книжке. Диалоговые окна с результатами выполнения программы SysInfo на разных процессорных платформах показаны ниже.

Рис. 14-1. Окна приложения SysInfo: 32-разрядная версия в 32-разрядной Windows (вверху слева); 32-разрядная версия в 32-разрядной версии Windows на двухьядерном процессоре (вверху справа); 32-разрядная версия в 64-разрядной Windows (внизу слева) и 64-разрядная версия в 64разрядной Windows (внизу слева)

SysInfo.cpp

/******************************************************************************

***

Module: SysInfo.cpp

Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre

*******************************************************************************

**/

#include “..\CmnHdr.h”

/*см. приложение А*/

#include <windowsx.h>

 

#include <tchar.h>

 

#include <stdio.h>

 

#include “Recourse.h”

 

#include <StrSafe>

 

Глава 14. Исследование виртуальной памяти.docx 465

///////////////////////////////////////////////////////////////////////////////

//Эта функция принимает число и преобразует его в строку,

//вставляя в нужных местах запятые.

PTSTR BigNumToString(LONG lNum, PTSTR szBuf, 0W0R0 chBufSize) {

TCHAR szNum[100];

StringCchPrintf(szNum, _countof(szNum), TEXT("%d"), lNun); NUNBERFMT nf;

nf.NumDigits = 0; nf.LeadingZero = FALSE; nf.Grouping = 3; nf.lpDecimalSep = TEXT(“.”); nf.lpThousandSep = TEXT(“,”); nf.NegativeOrder = 0;

GetNumberFormat(LOCALE_USER_DEFAULT, 0, szNum, &nf, szBuf, chBufSize); return(szBuf);

}

///////////////////////////////////////////////////////////////////////////////

void ShowCPUInfo(HWND hWnd, WORD wProcessorArchitecture, WORD wProcessorLevel, W0RD wProcessorRevision) {

TCHAR szCPUArch[64]

= TEXT("(unknown)");

TCHAR szCPULevel[64]

= TEXT("(unknown)");

TCHAR szCPURev[64]

= TEXT("(unknown)");

 

 

switch (wProcessorArchitecture) {

//Notice that AMD processors are seen as PROCESSOR_ARCHITECTURE_INTEL.

//In the Registry, the content of the "VendorIdentifier" key under

//HKEY_LOCAL_MACHIME\HARDWARE\DESCRIPTIOM\System\CentralProcessor\0

//is either "GenuineIntel" or "AuthenticAMD"

//

//Read http://download.intel.com/design/Xeon/applnots/24161831.pdf

//for Model numeric codes.

//http://www.amd.com/us-

en/assets/content_type/white_papers_and_tech_docs/

// 20734.pdf should be used for AMD processors Model numeric codes.

//

case PROCESSOR_ARCHITECTURE_INTEL:

_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("Intel"));

466 Часть III. Управление памятью

switch (wProcessorLevel) { case 3: case 4:

StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("80%c86"),

wProcessorLevel + TEXT(„0‟));

StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("%c%d"), HIBYTE(wProcessorRevision) + TEXT('A'), LOBYTE(wProcessorRevision));

break;

case 5:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT(“Pentium”));

StringCchPrintf(szCPURev, _countof(szCPURev),

TEXT(“Model %d, Stepping %d”),

HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision)); break;

case 6:

switch (HIBYTE(wProcessorRevision)) {//Model case 1:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Pentium Pro"));

break;

case 3: case 5:

_tcscpy_s(szCPULevel, _countof(szCPULevel),

TEXT(“Pentium II”)); break;

case 6:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Celeron"));

break;

case 7: case 8: case 11:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Pentium III"));

break;

case 9: case 13:

_tcscpy_s(szCPULevel, _countof(szCPULevel),

Глава 14. Исследование виртуальной памяти.docx 467

TEXT(“Pentium III”)); break;

case 10:

_tcscpy_s(szCPULevel, _countof( szCPULevel),

TEXT(“Pentium Xeon”)); break;

case 15:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Core 2 Duo"));

break;

default:

_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Unknown Pentium"));

break;

}

StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d, Stepping %d"),

HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision)); break;

case 15:

_tcscpy_s(szCPULevel, _countof(szCPULevel),TDCT("Pentium4")); StringCchPrintf(szCPURev, _countof(szCPURev),

TEXT("Model %d, Stepping %d"), HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision));

break;

}

break;

case PR0CESS0R_ARCHITECTURE_IA64:

_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("IA-64")); StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"),

wProcessorLevel);

StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c, Pass %d"),

HIBYTE(wProcessorRevislon) + TEXT('A'), LOBYTE(wProcessorRevision));

break;

case PR0CESS0R_ARCHITECTURE_AMD64:

_tcscpy_s(szCPUArch, _countof(szCPUArch),TEXT("AMD64")); StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"),

wProcessorLevel);

468 Часть III. Управление памятью

StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c, Pass

%d"),

HIBYTE(wProcessorRevision) + TEXT(„A‟),

LOBYTE(wProcessorRevision));

break;

case PROCESSOR_ARCHITECTURE_UNKNOWN: default:

_tcscpy_s (szCPUArch, _countof (szCPUArch), TEXT(“Unknown”)); break;

}

SetDlgItemText (hWnd, IDC_PROCARCH, szCPUArch); SetDlgItemText (hWnd, IDC_PROCLEVEL, szCPULevel); SetDlgItemText (hWnd, IDC_PROCREV, szCPURev);

}

void ShowBitness(HWND hWnd) { TCHAR szFullTitle[100]; TCHAR szTitle[32];

GetWindowText(hWnd, szTitle, _countof(szTitle));

#if defined(_WIN32)

BOOL bIsWow64 = FALSE;

if (!IsWow64Process(GetCurrentProcess(), &bIsWow64)) { chFAIL("Failed to get W0W64 state.");

return;

}

if (bIsWow64) {

StringCchPrintf(szFullTitle, _countof(szFullTitle), TEXT("32-bit Xs on W0W64"), szTitle);

} else {

StringCchPrintf(szFullTitle, _countof(szFullTitle), TEXT("32-bit %s on 32-bit Windows"), szTitle);

}

#elif defined(_WIN64)

//64-bit applications can only run on 64-bit Windows,

//so there is nothing special to check except the

//_WIN64 symbol set by the compiler. StringCchPrintf(szFullTitle, _countof(szFullTitle),

TEXT("64-bit %s"), szTitle);

#endif

SetWindowText(hWnd, szFullTitle);

}

Соседние файлы в предмете Программирование на C++