Издание четвертое windows ® для профессионалов создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows


Г ЛАВА 15Использование виртуальной памяти в приложенияхРис. 15-1



Pdf просмотр
страница39/68
Дата28.11.2016
Размер3.57 Mb.
Просмотров12471
Скачиваний0
1   ...   35   36   37   38   39   40   41   42   ...   68
Г ЛАВА 15
Использование виртуальной памяти в приложениях
Рис. 15-1.
продолжение
if (g_pSomeData == NULL) {
// память еще предстоит зарезервировать, g_rcMemMap.left, g_rcMemMap.top,
g_rcMemMap.right uMemMapWidth % uMaxPages, g_rcMemMap.bottom);
} else {
// проходим виртуальное адресное пространство, создавая карту памяти for (UINT uPage = 0; uPage < uMaxPages; uPage++) {
UINT uIndex = uPage * g_uPageSize / sizeof(SOMEDATA);
UINT uIndexLast = uIndex + g_uPageSize / sizeof(SOMEDATA);
for (; uIndex < uIndexLast; uIndex++) {
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(&g_pSomeData[uIndex], &mbi, sizeof(mbi));
int nBrush = 0;
switch (mbi.State) {
case MEM_FREE: nBrush = WHITE_BRUSH; break;
case MEM_RESERVE: nBrush = GRAY_BRUSH;
break;
case MEM_COMMIT:
nBrush = BLACK_BRUSH; break;
}
SelectObject(ps.hdc, GetStockObject(nBrush));
Rectangle(ps.hdc,
g_rcMemMap.left + uMemMapWidth / uMaxPages * uPage,
g_rcMemMap.top,
g_rcMemMap.left + uMemMapWidth / uMaxPages * (uPage + 1),
g_rcMemMap.bottom);
}
}
}
EndPaint(hwnd, &ps);
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
chHANDLE_DLGMSG(hwnd, WM_PAINT, Dlg_OnPaint);
chHANDLE_DLGMSG(hwnd, WM_DESTROY, Dlg_OnDestroy);
}
return(FALSE);
}
см. след. стр.

382
Ч АС Т Ь I I I
УПРАВЛЕНИЕ ПАМЯТЬЮ
Рис. 15-1.
продолжение
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, LPTSTR pszCmdLine, int) {
// получаем размер страниц для данного процессора si;
GetSystemInfo(&si);
g_uPageSize = si.dwPageSize;
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_VMALLOC), NULL, Dlg_Proc);
return(0);
}
//////////////////////////////// Конец файла //////////////////////////////////
Изменение атрибутов защиты
Хоть это и не принято, но атрибуты защиты, присвоенные странице или страницам переданной физической памяти, можно изменять. Допустим, Вы разработали код для управления связанным списком, узлы (вершины) которого хранятся в зарезервированном регионе. При желании можно написать функции, которые обрабатывали бы связанные списки и изменяли бы атрибуты защиты переданной памяти при старте на PAGE_READWRITE, а при завершении — обратно на Сделав так, Вы защитите данные в связанном списке от возможных жучков, скрытых в программе. Например, если какой то блок кода в Вашей программе из за наличия блуждающего указателя обратится к данным в связанном списке, возникнет нарушение доступа. Поэтому такой подход иногда очень полезен — особенно когда пытаешься найти трудноуловимую ошибку в своей программе.
Атрибуты защиты страницы памяти можно изменить вызовом
VirtualProtect:
BOOL VirtualProtect(
PVOID pvAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD Здесь
pvAddress указывает на базовый адрес памяти (который должен находиться в пользовательском разделе Вашего процесса,
dwSize определяет число байтов, для которых Вы изменяете атрибут защиты, а
flNewProtect содержит один из идентификаторов, кроме PAGE_WRITECOPY и Последний параметр,
pflOldProtect, содержит адрес переменной типа DWORD, в которую
VirtualProtect заносит старое значение атрибута защиты для данной области памяти. В этом параметре (даже если Вас не интересует такая информация) нужно передать корректный адрес, иначе функция приведет к нарушению доступа.
Естественно, атрибуты защиты связаны с целыми страницами памяти и не могут присваиваться отдельным байтам. Поэтому, если на процессоре с четырехкилобайто выми страницами вызвать
VirtualProtect, например, так + (3 * 1024), 2 * 1024,
PAGE_NOACCESS, то атрибут защиты PAGE_NOACCESS будет присвоен двум страницам памяти.

383
Г ЛАВА 15
Использование виртуальной памяти в приложениях 98 поддерживает лишь атрибуты защиты PAGE_NOACCESS, PAGE_READ
ONLY и PAGE_READWRITE. Попытка изменить атрибут защиты страницы на или PAGE_EXECUTE_READ приведет к тому, что эта область памяти получит атрибут PAGE_READONLY. А указав атрибут PAGE_EXECUTE_
READWRITE, Вы получите страницу с атрибутом Функцию
VirtualProtect нельзя использовать для изменения атрибутов защиты страниц, диапазон которых охватывает разные зарезервированные регионы. В таких случаях надо вызывать для каждого региона отдельно.
Сброс содержимого физической памяти
Windows 98 не поддерживает сброс физической памяти.
Когда Вы модифицируете содержимое страниц физической памяти, система пытается как можно дольше хранить эти изменения в оперативной памяти. Однако, выполняя приложения, система постоянно получает запросы на загрузку в оперативную память страниц из EXE файлов, DLL и/или страничного файла. Любой такой запрос заставляет систему просматривать оперативную память и выгружать модифицированные страницы в страничный файл 2000 позволяет программам увеличить свою производительность за счет сброса физической памяти. Вы сообщаете системе, что данные на одной или нескольких страницах памяти не изменялись. Если система в процессе поиска свободной страницы в оперативной памяти выбирает измененную страницу, то должна сначала записать ее в страничный файл. Эта операция отнимает довольно много времени и отрицательно сказывается на производительности. Поэтому в большинстве приложений желательно, чтобы система как можно дольше хранила модифицированные страницы в страничном файле.
Однако некоторые программы занимают блоки памяти на очень малое время, а потомим уже не требуется их содержимое. Для большего быстродействия программа может попросить систему не записывать определенные страницы в страничный файл.
И тогда, если одна из этих страниц понадобится для других целей, системе не придется сохранять ее в страничном файле, что, естественно, повысит скорость работы программы. Такой отказ от страницы (или страниц) памяти называется
сбросом фи
зической памяти (resetting of physical storage) и инициируется вызовом функции
VirtualAlloc с передачей ей в третьем параметре флага Если страницы, на которые Вы ссылаетесь при вызове
VirtualAlloc, находятся в страничном файле, система их удалит. Когда в следующий раз программа обратится к памяти, она получит новые страницы, инициализированные нулями. Если же Вы сбрасываете страницу, находящуюся в оперативной памяти, система помечает ее как не изменявшуюся, иона не записывается в страничный файл. Но, хотя ее содержимое
не обнуляется, читать такую страницу памяти уже нельзя. Если системе не понадобится эта страница оперативной памяти, ее содержимое останется прежним. Вином случае система может забрать ее в свое распоряжение, и тогда обращение к этой странице приведет к тому, что система предоставит программе новую страницу, заполненную нулями. А поскольку этот процесс нам неподвластен, лучше считать, что после сброса страница содержит только мусор.

384
Ч АС Т Ь I I I
УПРАВЛЕНИЕ ПАМЯТЬЮ
При сбросе физической памяти надо учитывать и несколько других моментов. Во первых, когда Вы вызываете
VirtualAlloc, базовый адрес обычно округляется до ближайшего меньшего значения, кратного размеру страница количество байтов — до ближайшего большего значения, кратного той же величине. Такой механизм округления базового адреса и количества байтов был бы очень опасен при сбросе физической памяти поэтому
VirtualAlloc при передаче ей флага MEM_RESET округляет эти значения прямо наоборот. Допустим, в Вашей программе есть следующий исходный код pnData = (PINT) VirtualAlloc(NULL, 1024,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
pn[0] = 100;
pn[1] = 200;
VirtualAlloc((PVOID) pnData, sizeof(int), MEM_RESET, Этот код передает одну страницу памяти, а затем сообщает, что первые четыре байта (
sizeof(int)) больше ненужны и их можно сбросить. Однако, как и при любых других действиях с памятью, эта операция выполняется только над блоками памяти,
размер которых кратен размеру страниц. В данном случае вызов завершится неудачно вернет NULL). Почему Дело в том, что при вызове VirtualAlloc Вы указали флаги базовый адрес, переданный функции, теперь округляется до ближайшего большего значения, кратного размеру страница количество байтов до ближайшего меньшего значения, кратного той же величине. Так делается, чтобы исключить случайную потерю важных данных. В предыдущем примере округление количества байтов до ближайшего меньшего значения дает 0, а эта величина недо пустима.
Второе, о чем следует помнить при сбросе памяти, — флаг MEM_RESET нельзя комбинировать (логической операцией OR) ни с какими другими флагами. Следующий вызов всегда будет заканчиваться неудачно pvMem = VirtualAlloc(NULL, 1024,
MEM_RESERVE | MEM_COMMIT | MEM_RESET, Впрочем, комбинировать флаг MEM_RESET с другими флагами все равно бессмыс ленно.
И, наконец, последнее. Вызов
VirtualAlloc с флагом MEM_RESET требует передачи корректного атрибута защиты страницы, даже несмотря на то что он не будет использоваться данной функцией.
Программа-пример MemReset
Эта программа, «15 MemReset.exe» (см. листинг на рис. 15 2), демонстрирует, как работает флаг MEM_RESET. Файлы исходного кода и ресурсов этой программы находятся в каталоге 15 MemReset на компакт диске, прилагаемом к книге.
Первое, что делает код этой программы, — резервирует регион и передает ему физическую память. Поскольку размер региона, переданный в
VirtualAlloc, равен байтам, система автоматически округляет это значение до размера страницы. Затем функция
lstrcpy копирует в этот буфер строку, и содержимое страницы оказывается измененным. Если система впоследствии сочтет, что ей нужна страница, содержащая наши данные, она запишет эту страницу в страничный файл. Когда наша программа попытается считать эти данные, система автоматически загрузит страницу из страничного файла в оперативную память.
После записи строки в страницу памяти наша программа спрашивает у пользователя, понадобятся ли еще эти данные. Если пользователь выбирает отрицательный

385
Г ЛАВА 15
Использование виртуальной памяти в приложениях ответ (щелчком кнопки No), программа сообщает системе, что страница не изменялась, для чего вызывает
VirtualAlloc с флагом Для демонстрации того факта, что память действительно сброшена, смоделируем высокую нагрузку на оперативную память, для чего:
1.
Получим общий размер оперативной памяти на компьютере вызовом
Global
MemoryStatus.
2.
Передадим эту память вызовом
VirtualAlloc. Данная операция выполняется очень быстро, поскольку система не выделяет оперативную память до тех пор, пока процесс не изменит какие нибудь страницы.
3.
Изменим содержимое только что переданных страниц через функцию
Zero
Memory. Это создает высокую нагрузку на оперативную память, и отдельные страницы выгружаются в страничный файл.
Если пользователь захочет оставить данные, сброс не осуществляется, и припер вой же попытке доступа к ним соответствующие страницы будут подгружаться в оперативную память из страничного файла. Если же пользователь откажется от этих данных, мы выполняем сброс памяти, система не записывает их в страничный файл, и это ускоряет выполнение программы.
После вызова
ZeroMemory я сравниваю содержимое страницы данных со строкой,
которая была туда записана. Если данные не сбрасывались, содержимое идентично, а если сбрасывались — то ли идентично, то ли нет. В моей программе содержимое никогда не останется прежним, поскольку я заставляю систему выгрузить все страницы оперативной памяти в страничный файл. Но если бы размер выгружаемой области был меньше общего объема оперативной памяти, тоне исключено, что исходное содержимое все равно осталось бы в памяти. Так что будьте осторожны!
MemReset.cpp
/******************************************************************************
Модуль: Автор Copyright (c) 2000, Джеффри Рихтер (Jeffrey Richter)
******************************************************************************/
#include "..\CmnHdr.h"
/* см. приложение А */
#include
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, LPTSTR pszCmdLine, int) {
chWindows9xNotAllowed();
TCHAR szAppName[]
= TEXT("MEM_RESET tester");
TCHAR szTestData[] = TEXT("Some text data");
// передаем страницу памяти и модифицируем ее содержимое pszData = (LPTSTR) VirtualAlloc(NULL, 1024,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
lstrcpy(pszData, szTestData);
Рис. 15-1.
Программа-пример MemReset
см. след. стр.

386
Ч АС Т Ь I I I
УПРАВЛЕНИЕ ПАМЯТЬЮ
Рис. 15-1.
продолжение
if (MessageBox(NULL, TEXT("Do you want to access this data later?"),
szAppName, MB_YESNO) == IDNO) {
// Мы хотим сохранить эту страницу физической памяти в нашем процессе, но ее данные нас больше не интересуют Скажем системе, что данные на этой странице не изменялись Примечание поскольку MEM_RESET разрушает данные, VirtualAlloc округляет параметры с базовым адресом и размером до наиболее безопасных значений Вот пример VirtualAlloc(pvData, 5000, MEM_RESET, PAGE_READWRITE)
// сбросит 0 страниц на процессорах с размером страниц более 4 Кб
// и 1 страницу на процессорах с четырехкилобайтовыми страницами Поэтому, чтобы вызов VirtualAlloc всегда был успешным, надо сначала вызвать VirtualQuery и определить точный размер страницы mbi;
VirtualQuery(pszData, &mbi, sizeof(mbi));
VirtualAlloc(pszData, mbi.RegionSize, MEM_RESET, PAGE_READWRITE);
}
// передаем объем памяти, равный размеру оперативной памяти mst;
GlobalMemoryStatus(&mst);
PVOID pvDummy = VirtualAlloc(NULL, mst.dwTotalPhys,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// изменяем содержимое всех страниц в регионе, чтобы все страницы модифицированные в оперативной памяти, записывались в страничный файл, mst.dwTotalPhys);
// сравниваем нашу страницу данных стем что было записано туда изначально if (lstrcmp(pszData, szTestData) == 0) {
// Данные на этой странице совпали стем, что мы туда записывали Функция ZeroMemory заставила систему записать нашу страницу в страничный файл, TEXT("Modified data page was saved."),
szAppName, MB_OK);
} else {
// Данные на этой странице не совпадают стем, что мы туда записывали ZeroMemory не заставила систему записать измененную страницу в страничный файл, TEXT("Modified data page was NOT saved."),
szAppName, MB_OK);
}
return(0);
}
//////////////////////////////// Конец файла //////////////////////////////////

387
Г ЛАВА 15
Использование виртуальной памяти в приложениях
Механизм Address Windowing Extensions
(только Windows 2000)
Жизнь идет впереди приложения требуют все больше и больше памяти — особенно серверные. Чем выше число клиентов, обращающихся к серверу, тем меньше его производительность. Для увеличения быстродействия серверное приложение должно хранить как можно больше своих данных в оперативной памяти и сбрасывать их на диск как можно реже. Другим классам приложений (базам данных, программам для работы с трехмерной графикой, математическими моделями и др) тоже нужно манипулировать крупными блоками памяти. И всем этим приложениям уже тесно в разрядном адресном пространстве.
Для таких приложений Windows 2000 предлагает новый механизм — Address Win dowing Extensions (AWE). Создавая AWE, Microsoft стремилась к тому, чтобы приложения могли:
í
работать с оперативной памятью, никогда не выгружаемой на диск операционной системой;
í
обращаться к таким объемам оперативной памяти, которые превышают размеры соответствующих разделов в адресных пространствах их процессов дает возможность приложению выделять себе один и более блоков оперативной памяти, невидимых в адресном пространстве процесса. Сделав это, приложение резервирует регион адресного пространства (с помощью
VirtualAlloc), ион становится адресным окном (address window). Далее программа вызывает функцию, которая связывает адресное окно с одним из выделенных блоков оперативной памяти. Эта операция выполняется чрезвычайно быстро (обычно за пару микросекунд).
Через одноадресное окно единовременно доступен лишь один блок памяти. Это,
конечно, усложняет программирование, так как при обращении к другому блоку приходится явно вызывать функции, которые как бы переключают адресное окно на очередной блок.
Вот пример, демонстрирующий использование AWE:
// сначала резервируем для адресного окна регион размером 1 Мб
ULONG_PTR ulRAMBytes = 1024 * 1024
PVOID pvWindow = VirtualAlloc(NULL, ulRAMBytes, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE);
// получаем размер страниц на данной процессорной платформе sinf;
GetSystemInfo(&sinf);
// вычисляем, сколько страниц памяти нужно для нашего количества байтов ulRAMPages = (ulRAMBytes + sinf.dwPageSize 1) / sinf.dwPageSize;
// создаем соответствующий массив для номеров фреймов страниц aRAMPages[ulRAMPages];
// выделяем страницы оперативной памяти (в полномочиях пользователя должна быть разрешена блокировка страниц в памяти, // выделяем память для нашего процесса на входе количество запрошенных страниц RAM,
// на выходе количество выделенных страниц RAM
см. след. стр.

388
Ч АС Т Ь I I I
УПРАВЛЕНИЕ ПАМЯТЬЮ на выходе специфический массив идентифицирующий выделенные страницы назначаем страницы оперативной памяти нашему окну адрес адресного окна ulRAMPages,
// число элементов в массиве aRAMPages);
// массив страниц RAM
// обращаемся к этим страницам через виртуальный адрес pvWindow
M
// освобождаем блок страниц оперативной памяти, // освобождаем RAM, выделенную нашему процессу на входе количество страниц RAM,
// на выходе количество освобожденных страниц RAM
aRAMPages);
// на входе массив, идентифицирующий освобождаемые страницы RAM
// уничтожаем адресное окно, 0, Как видите, пользоваться AWE несложно. А теперь хочу обратить Ваше внимание на несколько интересных моментов, связанных с этим фрагментом кода.
Вызов
VirtualAlloc резервирует адресное окно размером 1 Мб. Обычно адресное окно гораздо больше. Вы должны выбрать его размер в соответствии с объемом блоков оперативной памяти, необходимых Вашему приложению. Но, конечно, размер такого окна ограничен размером самого крупного свободного (и непрерывного!)
блока в адресном пространстве процесса. Флаг MEM_RESERVE указывает, что я просто резервирую диапазон адресов, а флаг MEM_PHYSICAL — что в конечном счете этот диапазон адресов будет связан с физической (оперативной) памятью. Механизм требует, чтобы вся память, связываемая с адресным окном, была доступна для чтения и записи поэтому в данном случае функции
VirtualAlloc можно передать только один атрибут защиты — PAGE_READWRITE. Кроме того, нельзя пользоваться функцией
VirtualProtect и пытаться изменять тип защиты этого блока памяти.
Для выделения блока в физической памяти надо вызвать функцию
AllocateUser
PhysicalPages:
BOOL AllocateUserPhysicalPages(
HANDLE hProcess,
PULONG_PTR pulRAMPages,
PULONG_PTR Она выделяет количество страниц оперативной памяти, заданное в значении, на которое указывает параметр
pulRAMPages, и закрепляет эти страницы за процессом,
определяемым параметром
hProcess.
Операционная система назначает каждой странице оперативной памяти
номер
фрейма страницы (page frame number). По мере того как система отбирает страницы памяти, выделяемые приложению, она вносит соответствующие данные (номер фрейма страницы для каждой страницы оперативной памяти) в массивна который указывает параметр
aRAMPages. Сами по себе эти номера для приложения совершенно бесполезны Вам не следует просматривать содержимое этого массива и тем бо

389
Г ЛАВА 15
Использование виртуальной памяти в приложениях лее что либо менять в нем. Вы не узнаете, какие страницы оперативной памяти будут выделены под запрошенный блок, да это и ненужно. Когда эти страницы связываются с адресным окном, они появляются в виде непрерывного блока памяти. А что там система делает для этого, Вас не должно интересовать.
Когда функция
AllocateUserPhysicalPages возвращает управление, значение в pulRAM
Pages сообщает количество фактически выделенных страниц. Обычно оно совпадает стем, что Вы передаете функции, но может оказаться и поменьше.
Страницы оперативной памяти выделяются только процессу, из которого была вызвана данная функция AWE не разрешает проецировать их на адресное пространство другого процесса. Поэтому такие блоки памяти нельзя разделять между процес сами.
Конечно, оперативная память — ресурс драгоценный, и приложение может выделить лишь ее незадействованную часть. Не злоупотребляйте механизмом если Ваш процесс захватит слишком много оперативной памяти, это может привести к интенсивной перекачке страниц на диски резкому падению производительности всей системы. Кроме того, это ограничит возможности системы в создании новых процессов, потоков и других ресурсов. (Мониторинг степени использования физической памяти можно реализовать через функцию
GlobalMemoryStatusEx.)
AllocateUserPhysicalPages требует также, чтобы приложению была разрешена блокировка страниц в памяти (те. у пользователя должно быть право «Lock
Pages in Memory»), а иначе функция потерпит неудачу. По умолчанию таким правом пользователи или их группы не наделяются. Оно назначается учетной записи Local System, которая обычно используется различными службами. Если
Вы хотите запускать интерактивное приложение, вызывающее
AllocateUser
PhysicalPages, администратор должен предоставить Вам соответствующее право еще до того, как Вы зарегистрируетесь в системе.
Теперь, создав адресное окно и выделив блок памяти, я связываю этот блок сок ном вызовом функции
MapUserPhysicalPages:
BOOL MapUserPhysicalPages(
PVOID pvAddressWindow,
ULONG_PTR ulRAMPages,
PULONG_PTR Ее первый параметр,
pvAddressWindow, определяет виртуальный адрес адресного окна, а последние два параметра,
ulRAMPages и aRAMPages, сообщают, сколько страниц оперативной памяти должно быть видимо через адресное окно и что это за страницы. Если окно меньше связываемого блока памяти, функция потерпит неудачу.
Функция
MapUserPhysicalPages отключает текущий блок оперативной памяти от адресного окна, если вместо параметра
aRAMPages передается NULL. Вот пример отключаем текущий блок RAM от адресного окна, ulRAMPages, NULL);

390
Ч АС Т Ь I I I
УПРАВЛЕНИЕ ПАМЯТЬЮ
Связав блок оперативной памяти с адресным окном, Вы можете легко обращаться к этой памяти, просто ссылаясь на виртуальные адреса относительно базового адреса адресного окна (в моем примере это
pvWindow).
Когда необходимость в блоке памяти отпадет, освободите его вызовом функции
FreeUserPhysicalPages:
BOOL FreeUserPhysicalPages(
HANDLE hProcess,
PULONG_PTR pulRAMPages,
PULONG_PTR Вправо активизируется так:
1.
Запустите консоль Computer Management MMC. Для этого щелкните кнопку выберите команду Run, введите «compmgmt.msc /a» и щелкните кнопку Если в левой секции нет элемента Local Computer Policy, выберите изменю команду Add/Remove Snap in. На вкладке Standalone в списке Snap ins
Added To укажите строку Computer Management (Local). Теперь щелкните кнопку, чтобы открыть диалоговое окно Add Standalone Snap in. В списке Avai lable Standalone Snap ins укажите Select Group Policy и выберите кнопку Add. В
диалоговом окне Select Group Policy Object просто щелкните кнопку Наконец, в диалоговом окне Add Standalone Snap in щелкните кнопку Close, а в диалоговом окне Add/Remove Snap in — кнопку OK. После этого в левой секции консоли Computer Management должен появиться элемент Local В левой секции консоли последовательно раскройте следующие элементы Computer Policy, Computer Configuration, Windows Settings, Security Settings и Local Policies. Выберите User Rights В правой секции выберите атрибут Lock Pages in Выберите изменю команду Select Security, чтобы открыть диалоговое окно Lock Pages in Memory. Щелкните кнопку Add. В диалоговом окне Select
Users or Groups добавьте пользователей и/или группы, которым Вы хотите разрешить блокировку страниц в памяти. Затем закройте все диалоговые окна,
щелкая в каждом из них кнопку Новые права вступят в силу при следующей регистрации в системе. Если
Вы только что сами себе предоставили право «Lock Pages in Memory», выйдите из системы и вновь зарегистрируйтесь в ней.
Ее первый параметр,
hProcess, идентифицирует процесс, владеющий данными страницами памяти, а последние два параметра сообщают, сколько страниц оперативной памяти следует освободить и что это за страницы. Если освобождаемый блок в данный момент связан с адресным окном, он сначала отключается от этого окна.
И, наконец, завершая очистку, я освобождаю адресное окно. Для этого я вызываю
VirtualFree и передаю ей базовый виртуальный адрес окна, нуль вместо размера региона и флаг В моем простом примере создается одноадресное окно и единственный блок памяти. Это позволяет моей программе обращаться к оперативной памяти, которая никогда не будет сбрасываться на диск. Однако приложение может создать несколько адресных окон и выделить несколько блоков памяти. Эти блоки разрешается связывать с любым адресным окном, но операционная система не позволит связать один блок сразу с двумя окнами.
1   ...   35   36   37   38   39   40   41   42   ...   68


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал