Управление памятью в операционной системе WINDOWS, страница 5

VirtualAlloc(p, MEGABYTE, MEM_COMMIT, PAGE_READWRITE);

break;

case '4':

exit(0);

default:

cout<<"\nЧего-чего?\n";

valid=0;

}

if (p&&valid)

cout<<"Блок памяти @ "<<hex<<(unsigned int)p<<"\n";

if (!p&&valid) cout<<"Ошибка выделения памяти!\n";

} while (1);

}

В появившемся меню выберите пункт 1. Программа выделит блок памяти установленного размера, а затем освободит его. На большинстве современных компьютеров эта процедура будет выполнена в течение всего нескольких секунд. За это время Windows должна настроить все необходимые записи в таблице соответствия страниц, определить доступный объем физической памяти и создать необходимое количество страниц виртуальной памяти. Если объем физической памяти вашего компьютера превышает 75 Мбайт, для наглядности попробуйте использовать блок памяти большего размера. Выберите пункт 1 несколько раз, чтобы получить представление о том, насколько быстро выполняется процедура выделения и освобождения достаточно больших участков памяти.

Теперь попробуйте выбрать пункт 2. При этом программа не будет выделять физическую или виртуальную память объемом 64 Мбайт, а лишь зарезервирует диапазон адресов необходимого размера. Это происходит настолько быстро, что вы даже не сможете заметить, что что-либо произошло. Конечно, если вы зарезервировали диапазон адресов, это не значит, что вы сможете немедленно приступить к использованию соответствующей памяти.

Чтобы проверить, как выполняются процедуры резервирования адресов и выделения конкретной памяти в комплексе, выберите пункт 3. При этом программа резервирует адресное пространство указанного объема, а затем выделяет всего один мегабайт памяти из этого адресного пространства. Таким образом, моделируется ситуация, в которой вы на всякий случай резервируете достаточно большой участок непрерывной памяти, однако используете лишь небольшой фрагмент этого участка. Такое поведение, в частности, напоминает работу программы, оцифровывающей видеосигнал, о которой мы говорили ранее. Выбрав пункт 3 тестовой программы, вы заметите, что резервирование адресного пространства и последующее выделение памяти в этом пространстве выполняются фактически мгновенно. Естественно, ведь выделяется лишь один мегабайт из шестидесяти четырех. В большинстве ситуаций, используя подобный подход, вы сможете добиться более гладкой работы ваших программ. Другими словами, если вы зарезервируете 10 Мбайт, а затем выделите всю эту память последовательно блоками по одному мегабайту, у пользователя возникнет ощущение, что ваша программа работает быстрее, чем если бы было выполнено выделение всех 10 Мбайт за одну операцию.

Работа с атрибутами страниц

Определенно одним из основных преимуществ использования VirtualAlloc является возможность управления уровнем доступа к страницам оперативной памяти как во время ее выделения, так и позже (при помощи функции VirtualProtect). Разумное использование этой возможности может существенно упростить разработку многих приложений.

Для примера рассмотрим код в листинге 2. Это библиотечная функция, которая возвращает указатель на статическую строку. В реальной жизни эта функция может располагаться в библиотеке DLL, однако для целей этой программы мы включим ее в состав основного исполняемого файла наряду с функцией main.

Листинг 2. Передача статической строки в режиме только для чтения

#include <stdio.h>

#include <string.h>

#include <windows.h>

char *getmsg()

{

static char *msg;

if (msg==NULL)

{

char tmp[1024];

DWORD oldprot;

FILE *f;

f=fopen("strings.txt", "r");

if (!f) return NULL;

fgets(tmp, sizeof(tmp), f);

// Выделяет целую страницу памяти, что приемлемо для данного примера

msg=(char *)VirtualAlloc(NULL, strlen(tmp)+1, MEM_COMMIT, PAGE_READWRITE);

strcpy(msg, tmp);

fclose(f);

// Назначает уровень доступа к странице памяти только для чтения

VirtualProtect(msg, strlen(msg)+1, PAGE_READONLY, &oldprot);