AWE

Материал из DRKB

Расширение адресной оболочки Windows


Описание работы с AWE[править | править код]

Этот раздел описывает расширение адресной оболочки Windows (Address Windowing Extention, AWE). Это расширение Windows 2000 предоставляет возможность пользовательским приложениям адресовать более чем 32 бита адресного пространства.

Windows NT и Windows 2000 предоставляют своим приложениям сплошное 32-х битовое адресное пространство, которое описывает 4 Гб виртуальной памяти. Это адресное пространство обычно разбито таким образом, что только 2 Гб непосредственно доступны для нужд приложения. Другие 2 Гб доступны только закрытому коду, принадлежащему операционной системе. Добавим, что начиная с Windows NT 4 SP 3 и Windows NT Server Enterprise Edition/Windows 2000 Advanced Server на базе процессора x86 на нужды приложения выделяется 3 Гб, а закрытому коду - 1 Гб.

AWE является набором расширений, которые предоставляют пользователю возможность пользователю напрямую выделять и фиксировать страницы в оперативной памяти. В этом случае приложения могут быстро оперировать с физической памятью, превышающей 4 Гб. Некоторые приложения, связанные с интенсивной обработкой данных, такие как системы управления базами данных, а также научные и инженерные приложения, нуждаются в доступе к очень огромным кэшам данных. В этом случае, размер кэша ограничивается 2 Гб, доступными приложениями, что иногда является жестким ограничением. В этих случаях, приложения могут использовать под кэш небольшие объемы данных.

AWE решает эту проблему путем разрешения приложению непосредственно адресовать гигантскую память, в то время как оно может использовать и обычную 32-х битную адресацию. AWE предоставляет для приложений возможность иметь под кэш более чем 4 Гб (при условии, что существует соответствующая физическая память).

Использование AWE связано с некоторыми ограничениями на использование такой памяти, главным образом эти ограничения связаны с предоставлением критичного по скорости распределением, перераспределением и освобождением памяти.

  • Виртуальное адресное пространство, выделенное средствами AWE, нельзя разделить с другими процессами (и, поэтому, оно не является наследуемым). Невозможно также две различные страницы виртуального адресного пространства спроецировать на одну страницу оперативной памяти. Эти ограничения позволяют сделать быстрой операции перепроецирования и очистки памяти при ее освобождении.
  • Физическая память, которая может быть выделена в AWE регионе, ограничена количеством физической памяти, которая присутствует на компьютере. Так как эта память является фиксированной, то она блокируется до тех пор, пока приложение ее не освободит (либо до тех пор, пока приложение существует). Физические страницы памяти, выделенные для данного процесса, могут быть спроектированы в любой AWE регион, связанный с этим процессом. Приложение, которое использует AWE, должно быть очень аккуратным, поскольку может забрать на свои нужды столько памяти, что оставшиеся приложения будут иметь интенсивный обмен с файлом подкачки, либо будет предотвращена попытка создания новых процессов и потоков по причине нехватки ресурсов. Используйте функцию GlobalMemoryStatusEx для того, чтобы отследить использование физической памяти.
  • Виртуальное адресное пространство, выделенное средствами AWE, всегда доступно для чтения/записи, поэтому к ней неприменимы вызовы функции VirtualProtect (поскольку не существует памяти, доступной только для чтения, памяти без доступа, защиты страниц и прочих спецификаторов).
  • Диапазон адресов AWE не может быть использован в качестве буфера для графических или видео вызовов.
  • Регион памяти AWE не может быть разбит на части, которые затем можно было бы удалить. Весь регион может быть удален только как единое целое, когда это понадобиться. Для этого вы должны указать флаг MEM_RELEASE (но не MEM_DECOMMIT) при вызове VirtualFree.
  • Приложения, которые используют AWE, не могут выполняться в режиме эмуляции. Поэтому те приложения, на архитектуре x86, которые используют AWE, должны быть перекомпилированы на других процессорах, тогда как другие большинство других приложений может быть запущено на других платформах в режиме эмуляции.

Решение адресовать физическую память следует в большей степени из получаемых при этом выгод. Вот некоторые выгоды использования AWE:

  • Небольшое число функций, использующихся для операций с AWE памятью.
  • AWE поддерживается на всех платформах, на которых реализована Windows 2000, включая 64-х битную версию Windows 2000.
  • AWE предоставляет очень быстрое перераспределение хранимых данных. Перераспределение осуществляется путем использования таблиц виртуальной памяти без перемещения данных в физической памяти.
  • Гранулярность размера AWE страницы соответствует типу процессора (для архитектуры x86 это 4 Кб) которые более полезны для приложений, чем большие страницы (например, 2 Мб, 4 Мб на x86).

Для того чтобы получить привилегию фиксирования страниц в памяти, администратор должен добавить значение атрибута "Lock Page in Memory" в правах пользователя. Установить этот параметр можно выбрав "Панель управления → Администрирование → Локальная политика безопасности → Локальная политика → Назначение прав пользователя → Закрепление страниц в памяти" (Control panel → Administrative tools → Local security policy → Local policy → User right assigment → Lock pages in memory). Для более детальной информации по этому вопросу смотрите раздел "Права пользователей" в справочной системе по Windows 2000.

Следующие функции реализуют API расширения адресной оболочки Windows (AWE API):

  • VirtualAlloc - Резервирует диапазон виртуального адресного пространства для использования под AWE (атрибут MEM_PHYSICAL).
  • AllocateUserPhysicalPages - Выделяет физическую память для использования с AWE.
  • MapUserPhysicalPages - Проецирует (или сводит на нет) виртуальное пространство AWE на произвольный набор физических страниц, полученных при помощи вызова AllocateUserPhysicalPages.
  • MapUserPhysicalPagesScatter - Проецирует (или сводит на нет) виртуальное пространство AWE на произвольный набор физических страниц, полученных при помощи вызова AllocateUserPhysicalPages, позволяющей организовать сложное проецирование.
  • FreeUserPhysicalPages - Освобождает физическую память, которая была выделена под AWE.


MapUserPhysicalPages[править | править код]

Функция MapUserPhysicalPages проецирует выделенную ранее область физической памяти в указанное адресное пространство AWE-региона виртуальной памяти. Для того, чтобы произвести "групповое" проецирование или разпроецирование для нескольких регионов, вы должны воспользоваться функцией MapUserPhysicalPagesScatter.

{ Вариант 1 }
function MapUserPhysicalPages(
  lpAddress: Pointer;     // начальный адрес области памяти 
  NumberOfPages: UINT;    // размер физической памяти в страницах 
  var UserPfnArray: UINT  // первый элемент массива фреймов страниц 
): Boolean; overload;

{ Вариант 2 }
function MapUserPhysicalPages(
  lpAddress: Pointer;     // начальный адрес области памяти 
  NumberOfPages: UINT;    // размер физической памяти в страницах 
  UserPfnArray: Pointer   // указатель на массив фреймов страниц 
): Boolean; overload;


Параметры

lpAddress
Указатель на начальный адрес области памяти, на который будет спроецирована физическая память. Это значение должно находиться внутри диапазона виртуального адресного пространства приложения, выделенного при помощи функции VirtualAlloc с атрибутом, указывающим принадлежность выделяемого фрагмента памяти к AWE-региону.
NumberOfPages
Задает размер в страницах физической памяти (и виртуального адресного пространства). Виртуальное адресное пространство непрерывно и начинается с адреса, указанного в параметре lpAddress. Кадры физической памяти задаются параметром UserPfnArray. Общее число страниц не может превышать то количество страниц, которое было выделено при вызове AllocateUserPhysicalPages.
UserPfnArray
Задает начальный элемент массива фреймов страниц (вариант 1). Эти фреймы должны быть спроецированы в область памяти, на которую указывает параметр lpAddress. Указанный массив должен содержать по меньшей мере NumberOfPages элементов типа UINT.

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

Указание значение nil этому параметру (вариант 2), позволяет провести распроецирование указанного диапазона адресов. При этом указанные страницы не освобождаются в физической памяти, для этого нужно выполнять специальный вызов FreeUserPhysicalPages.


Возвращаемое значение

  • В случае удачного завершения функция возвращает True.
  • В случае ошибки (когда не было выполнено ни частичного, ни полного проецирования) функция вернет False. Для получения расширенной информации об ошибке следует сделать вызов GetLastError.


Описание

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

Вы не можете спроецировать на виртуальное адресное пространство процесса страницы, которые не были выделены при помощи метода AllocateUserPhysicalPages.

Если со страницы физической памяти было снято проецирование на виртуальное адресное пространство процесса, то это не приводит к освобождению страницы физической памяти. Чтобы освободить страницу в физической памяти, необходимо выполнить вызов FreeUserPhysicalPages.

Страницы физической памяти могут располагаться где угодно. Вы не можете делать каких либо предположений относительно расположения страниц в оперативной памяти. Если со страницы физической памяти было снято проецирование на виртуальное адресное пространство процесса, то это не приводит к освобождению страницы физической памяти. Чтобы освободить страницу в физической памяти, необходимо выполнить вызов FreeUserPhysicalPages.

Для того, чтобы только разпроецировать страницы в физической памяти, необходимо передать в параметре UserPfnArray значение nil.

В многопроцессорных системах данная функция сохраняет согласованность буферов на аппаратном уровне. По выходе из функции гарантируется, что все потоки и процессы будут видеть корректное проецирование страниц.


Требования

  • Windows NT/2000: Требуется Windows 2000 или более поздняя версия
  • Windows 95/98: Не поддерживается
  • Библиотека: Kernel32.dll
  • Подключаемый модуль: Windows


AllocateUserPhysicalPages[править | править код]

Функция AllocateUserPhysicalPages выделяет страницы физической памяти, которые могут быть впоследствии спроецированы или переспроецированы в любой регион расширения адресной оболочки Windows (AWE-регион) указанного процесса.

function AllocateUserPhysicalPages(
  hProcess: THandle;           // дескриптор процесса
  var NumberOfPages: Cardinal; // число страниц
  var UserPfnArray: Pointer    // адрес хранилища
): Boolean; stdcall;


Параметры

[in] hProcess
Дескриптор процесса. Функция выделяет память в виртуальном адресном пространстве этого процесса. Пользователь, запускающий вызывающее приложение, должен иметь привилегию фиксирования страниц памяти (Lock Pages in Memory) для данного процесса. Если это не выполнено, вызов функции завершится неудачно.
[in/out] NumberOfPages
Указывает размер (в страницах) физической памяти, которая будет выделена. Используйте функцию GetSysInfo для того, чтобы определить размер страницы на вашем компьютере. В этом параметре также возвращается число страниц, которые были действительно выделены. Это число может быть меньше запрашиваемого.
[out] UserPfnArray
Задает виртуальный адрес, по которому будут сохранены номера фреймов страниц выделенной памяти. Размер памяти, выделенной по данному указателю, должен по меньшей мере вместить NumberOfPages элементов типа Cardinal.

Важно! Не пытайтесь модифицировать содержимое этого буфера. Он содержит данные, принадлежащие операционной системе, повреждение которых можeт повлечь за собой катастрофические последствия. В этом буфере не содержится никакой информации, необходимой вашему приложению.


Возвращаемое значение

В случае успешного завершения функция возвращает True. В результате были выделены несколько страниц физической памяти. Это число может быть меньше запрашиваемого, поэтому вы должны всегда проверять значение NumberOfPages для того, чтобы узнать, какое именно количество страниц было выделено. Фреймы всех выделенных страниц последовательно помещаются в память на которую указывает параметр UserPfnArray.

В случае ошибки функция вернет False. Для получения расширенной информации об ошибке следует сделать вызов GetLastError.


Описание

Функция AllocateUserPhysicalPages используется для выделения физической памяти. Память, выделяемая этой функцией, должна физически присутствовать в системе. Выделенная однажды, она фиксирует свое расположение в памяти и более не управляется менеджером памяти Windows 2000.

Физическая страница памяти не может быть спроецирована по более чем одному виртуальному адресу.

Физическая страница может находиться по любому физическому адресу. Вы не должны делать никаких предположений относительно смежности физических страниц.

Используйте функцию GetSystemInfo для того, чтобы определить размер страницы на вашем компьютере.


Требования

  • Windows NT/2000: Требуется Windows 2000 или более поздняя версия
  • Windows 95/98: Не поддерживается
  • Библиотека: Kernel32.dll
  • Подключаемый модуль: Не описана


MapUserPhysicalPagesScatter[править | править код]

Функция MapUserPhysicalPagesScatter проецирует выделенную ранее область физической памяти в указанное адресное пространство AWE-региона виртуальной памяти. В отличие от функции MapUserPhysicalPages, данная функция производит "групповое" проецирование или разпроецирование для нескольких регионов.


{ Вариант 1 }
function MapUserPhysicalPagesScatter(
  var lpAddresses: Pointer; // начальный адрес области памяти 
  NumberOfPages: UINT;      // размер физической памяти в страницах 
  var UserPfnArray: UINT    // первый элемент массива фреймов страниц 
): Boolean; overload;

{ Вариант 2 }
function MapUserPhysicalPagesScatter(
  var lpAddresses: Pointer; // начальный адрес области памяти 
  NumberOfPages: UINT;      // размер физической памяти в страницах 
  UserPfnArray: Pointer     // указатель на массив фреймов страниц 
): Boolean; overload;


Параметры

[in] lpAddresses
Задает начальный элемент массива адресов, в которые будет спроецирована физическая память. Значение каждого адреса должно находиться внутри диапазона виртуального адресного пространства приложения, выделенного при помощи функции VirtualAlloc с атрибутом, указывающим принадлежность выделяемого фрагмента памяти к AWE-региону. Значение NumberOfPages показывает количество элементов массива. Заметим, что значения указателей могут принадлежать нескольким различным AWE-регионам.
[in] NumberOfPages
Задает размер в страницах физической памяти (и виртуального адресного пространства). Адреса страниц в виртуальном адресном пространстве содержаться в массиве, начальный элемент которого lpAddresses. Кадры физической памяти задаются параметром UserPfnArray. Общее число страниц не может превышать то количество страниц, которое было выделено при вызове AllocateUserPhysicalPages.
[in] UserPfnArray
Задает начальный элемент массива фреймов страниц (вариант 1). Эти фреймы должны быть спроецированы в область памяти, на которую указывает параметр lpAddress. Указанный массив должен содержать по меньшей мере NumberOfPages элементов типа UINT.

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

Указание значение nil этому параметру (вариант 2), позволяет провести распроецирование указанного диапазона адресов. При этом указанные страницы не освобождаются в физической памяти, для этого нужно выполнять специальный вызов FreeUserPhysicalPages.


Возвращаемое значение

В случае удачного завершения функция возвращает True.

В случае ошибки (когда не было выполнено ни частичного, ни полного проецирования) функция вернет False. Для получения расширенной информации об ошибке следует сделать вызов GetLastError.


Описание

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

Вы не можете спроецировать на виртуальное адресное пространство процесса страницы, которые не были выделены при помощи метода AllocateUserPhysicalPages.

Если со страницы физической памяти было снято проецирование на виртуальное адресное пространство процесса, то это не приводит к освобождению страницы физической памяти. Чтобы освободить страницу в физической памяти, необходимо выполнить вызов FreeUserPhysicalPages.

Страницы физической памяти могут располагаться где угодно. Вы не можете делать каких либо предположений относительно расположения страниц в оперативной памяти. Если со страницы физической памяти было снято проецирование на виртуальное адресное пространство процесса, то это не приводит к освобождению страницы физической памяти. Чтобы освободить страницу в физической памяти, необходимо выполнить вызов FreeUserPhysicalPages.

В многопроцессорных системах данная функция сохраняет согласованность буферов на аппаратном уровне. По выходе из функции гарантируется, что все потоки и процессы будут видеть корректное проецирование страниц.


Требования

  • Windows NT/2000: Требуется Windows 2000 или более поздняя версия
  • Windows 95/98: Не поддерживается
  • Библиотека: Kernel32.dll
  • Подключаемый модуль: Windows


FreeUserPhysicalPages[править | править код]

Функция FreeUserPhysicalPages освобождает физические страницы памяти, которые были ранее выделены при помощи вызова AllocateUserPhysicalPages. Если текущие страницы были спроецированы в AWE-регион, то при вызове автоматически произойдет очищение проецирования. Заметим, что указанный вызов никак не затронет виртуальное адресное пространство, занимающее AWE-регион.


function FreeUserPhysicalPages(
  hProcess: THandle,           // дескриптор процесса
  var NumberOfPages: Cardinal, // количество страниц для освобождения
  var UserPfnArray: DWORD      // виртуальный адрес фреймов освобождаемых страниц
): Boolean; stdcall;


Параметры

[in] hProcess
Дескриптор процесса. Функция освобождает память в виртуальном адресном пространстве этого процесса.
[in/out] NumberOfPages
Указывает размер физической памяти в страницах, которая будет освобождена. При возвращении с случае ошибки возвращает количество страниц в памяти, которые действительно были освобождены.
[in] UserPfnArray
Задает виртуальное адресное пространство, которое содержит фреймы страниц, которые должны быть освобождены.


Возвращаемое значение

При удачном завершении функция возвращает True.

В случае возникновения ошибки функция вернет False. В этом случае параметр NumberOfPages показывает, сколько страниц было освобождено в действительности. Для получения расширенной информации об ошибке выполните вызов GetLastError.


Описание

В случае нескольких процессоров эта функция поддерживает согласованное выполнение на уровне аппаратного переводного буфера. При выходе из этой функции, для всех потоков и процессов гарантируется корректное проецирование.


Требования

  • Windows NT/2000: Требуется Windows NT 2000 или более поздняя версия
  • Windows 95/98: Не поддерживается
  • Библиотека: Kernel32.dll
  • Подключаемый модуль: Не описана


Author: Mystic, 2002
ID: 02039