Этот раздел описывает расширение адресной оболочки 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 Гб.

 

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

Платформа WinNT(XP) не допускает возможность непосредственного доступа к памяти средствами Win32API. В этом случае программист должен или написать свой драйвер доступа к физической памяти или использовать native kernel32 функции ядра.

Рассмотрим второй вариант использующий объект "проекция файла" (file-mapping object), представляющем собой блок памяти(раздел) доступный двум и более процессам для совместного использования.

Совместное использование данных с помощью объекта "раздел" происходит следующим образом: Задав атрибуты с помощью функции

 

Например через атомы:

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

 

Сегодня мы попытаемся написать программу, которая будет показывать состояние памяти компа. Для начала определим что она будет делать. Ну самое главное что нам нужно, это сотояние физической памяти и загруженность ее в %. А дальше, по своему вкусу, добавим еще состояние виртуальной и страничной памяти. Начнем. Создай новый проект на Делфи ( File->New->Application). Теперь подумай, как тебе удобней отображать состояние памяти. Для меня лучше в Label, но можно и Edit. Ну это на твое усмотрение. Кидай на форму 7 компонентов Label (в них будет отображаться значение) и еще 7 (это будут пояснения: загруженность, всего физической, использовано физической, всего страничной, использовано страничной, всего виртуальной, использовано виртуальной). Какие не нужны, те отбрось ;) . Теперь кинь таймер (из вкладки System). Это будет наш главный элемент., поэтому поставь интервал по своему усмотрению (у меня он 400). Этот интервал будет отвечать за частоту обновления полей. Ну и для красоты брось ProgressBar ( из вкладки Win32). У тебя должно получиться что-то типа этого: Теперь приступим непосредственно к кодингу. Весь код мы будем писать в процедуру запуска таймера. А вот и код:

 

Addr                Возвращает указатель на объект.

 

AllocMem        Выделяет на куче блок памяти заданного размера, заполняет его нулями и возвращает указатель на начало блока.

 

CompareMem        Выполняет бинарное сравнение двух участков памяти.

 

GetHeapStatus Возвращает текущее состояние диспетчера памяти.

 

GetMemoryManager Возвращает значения указателей полей текущего диспетчера памяти.

 

IsMemoryManagerSet Определяет, используется в настоящий момент диспетчер памяти, установленный по умолчанию, или был установлен другой диспетчер.

 

Ptr                 Возвращает указатель на адрес памяти, переданный в качестве аргумента.

 

SizeOf                 Возвращает размер памяти, занимаемый переменной.

 

SetMemoryManager Устанавливает значения полей диспетчера памяти.

 

SysFreeMem        Высвобождает память, используемую динамической переменной.

 

SysGetMem         Выделяет блок памяти заданного размера и возвращает указатель на него.

 

SysReallocMem Изменяет размер динамически распределенного блока памяти.

 

Code:

{Act: 0 - Очистка атомов, 1 - чтение атомов, 2 - запись атомов}

{Uniq - Уникальный идентификатор}

{AtomNfo - Информация для записи}

Function AtomDo(Act:integer;Uniq,AtomNfo:string);

 

Procedure CleanAtoms;

var P:PChar;

i:Word;

begin

GetMem(p, 256);

   For i:=0 to $FFFF do

   begin

     GlobalGetAtomName(i, p, 255);

    if StrPos(p, PChar(Uniq))<>nil then GlobalDeleteAtom(i);

   end;

  FreeMem(p);

end;

 

Function ReadAtom:string;

var P:PChar;

i:Word;

begin

   GetMem(p, 256);

   For i:=0 to $FFFF do

  begin

   GlobalGetAtomName(i, p, 255);

   if StrPos(p, PChar(Uniq))<>nil then break;

  end;

     result:=StrPas(p+length(Uniq));

     FreeMem(p);

end;

 

begin

 

case Act of

0 : CleanAtoms;

1 : Result:=ReadAtom;

2 : begin

     CleanAtoms;

     GlobalAddAtom(PChar(Uniq+AtomNfo));

     end;

end;

 

 

Code:

function GetMemoryTotalPhys : DWord;

var

memStatus: TMemoryStatus;

begin

memStatus.dwLength := sizeOf ( memStatus );

GlobalMemoryStatus ( memStatus );

Result := memStatus.dwTotalPhys;

end;

 

 

 

Code:

function LastInput: DWord;

var

LInput: TLastInputInfo;

begin

LInput.cbSize := SizeOf(TLastInputInfo);

GetLastInputInfo(LInput);

Result := GetTickCount - LInput.dwTime;

end;

 

 

//Example:

procedure TForm1.Timer1Timer(Sender: TObject);

begin

Label1.Caption := Format('System Idle since %d ms', [LastInput]);

end;

 

 

// The GetLastInputInfo function retrieves the time

// of the last input event.

// Minimum operating systems: Windows 2000

 

 

Code:

var

Status : TMemoryStatus;

begin

Status.dwLength := sizeof( TMemoryStatus );

GlobalMemoryStatus( Status );

...

 

 

Code:

{$IFNDEF WIN32}

const WF_WINNT = $4000;

{$ENDIF}

 

function IsNT : bool;

{$IFDEF WIN32}

var

  osv : TOSVERSIONINFO;

{$ENDIF}

begin

result := true;

{$IFDEF WIN32}

GetVersionEx(osv);

if osv.dwPlatformId = VER_PLATFORM_WIN32_NT then exit;

{$ELSE}

  if ((GetWinFlags and WF_WINNT) = WF_WINNT ) then exit;

{$ENDIF}

result := false;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

if IsNt then

   ShowMessage('Running on NT')

else

   ShowMessage('Not Running on NT');

end;