ООП - это очень просто?

Выпуск № 7

Уважаемые подписчики, слухи о смерти этой рассылки несколько преувеличены, как писал в свое время Марк Твен. Просто семестр выдался дико занятым. Но вот уже получил уже и предупреждение о том, что если не сделаю выпуск, то рассылку прикроют :((.

Даже есть вопрос о том, как вставить запись внутрь списка. Правда, автор вопроса, видимо, решил задачу сам, поскольку на уточняющий вопрос не ответил.  И хотя у меня есть несколько заготовок выпусков по теме "Объектно-ориентированное программирование", я решил написать о другом. Этим объясняется знак вопроса в названии рассылки. Впрочем, понимайте его как хотите :))

Итак, я решил рассказать, как в Borland Pascal получить доступ к динамической памяти размером больше 64 килобайт.

Как получить в свое распоряжение более 64 килобайт памяти

Проблема заключается в том, что когда создавалась операционная система DOS, и не предполагалось, что какой-либо программе может понадобиться для работы память больше 64 килобайт. Такая цифра определялась существующей техникой. А именно: за один раз процессор мог передать 16-битный адрес. 216 как раз и равно 65536 = 64 К. Затем были созданы элементы памяти большой емкостью. И был придуман способ работы с такой памятью: адрес поделили на сегмент и смещение в этом сегменте. Можно было указывать сегмент, а в нем адресовать еще 64 Кбайт ячеек памяти. Фактически адрес вычислялся по формуле Сегмент*16 + Смещение.

Как Вы знаете, сейчас и десятки мегабайт оперативной памяти уже считается склерозом. Механизм для надежной работы с большими объемами памяти был разработан только в Windows, начиная только с процессора 80286. Это, так называемый защищенный режим процессора (Protected mode). Обычный режим был назван "реальным" (Real mode). Однако, для программ ДОСовских, к каким относятся "обычные" программы, написанные в Borland Pascal, сохранили ограничение в пресловутые 64 К. То есть, за один раз можно адресовать только 64 К памяти.

ДОСовская программа, если хочет получить к большим объемам памяти, должна перейти в защищенный режим. В среде такое Borland Pascal переключение возможно только в самом начале работы с помощью пункта меню: Compile -> Target. При этом программа будет пользоваться двумя файлами. Расширения защищенного режима Borland Pascal реализованы через два компонента: DPMI-сервер (файл DPMI16BI.OVL) и администратор этапа выполнения (файл RTM.EXE). Они должны быть в той папке, из которой запускается программа (вне среды разработки программ).

Работа с памятью реализуется с помощью функций и процедур модуля WinAPI и указателей.

Функция GlobalAlloc используется для распределения блоков памяти. Для их освобождения применяется функция GlobalFree. Администратор памяти поддерживает три типа блоков памяти: фиксированный, перемещаемый и выгружаемый. Фиксированный блок остается в одних и тех же адресах физической памяти. Перемещаемый блок может перемещаться в физической памяти и освобождать место для других запросов на выделение памяти, а выгружаемые блоки могут выгружаться из памяти, освобождая место для других блоков. С помощью передаваемых GlobalAlloc флагов вы можете выбрать один из этих трех типов:

Прикладная программа обычно выделяет только перемещаемые блоки памяти, которые представляются типом THandle в модуле
WinAPI. Описатель памяти - это значение размером в слово, которое идентифицирует блок памяти аналогично тому, как описатель файла - это значение размером в слово, идентифицирующее открытый файл.

Перед тем как вы сможете получить доступ к памяти, его нужно заблокировать с помощью функции GlobalAlloc, а когда вы закончите к нему обращаться, его нужно разблокировать с помощью функции GlobalUnlock. GlobalLock возвращает полный 32-разрядный указатель на первый байт блока. Смещение указателя всегда равно 0. В защищенном режиме DOS селектор указателя - это тоже самое, что описатель блока, но в Windows это не всегда так.

Правильная последовательность вызовов для выделения, блокировки, разблокировки или освобождения блока показана в приведенном ниже примере.

program AboutGlobalAlloc;
{Должна выполняться в защищенном режиме!!}
uses WinDOS, WinAPI;
var
  H : THandle;
  P : Pointer;
  m : Longint;
BEGIN
  m:=MemAvail;         {Запомним размер доступной памяти в начале работы программы }
  WriteLn(MemAvail);  { Вывод на экран сообщения об объеме доступной памяти }
  H := GlobalAlloc(gmem_Moveable, 1008192);    { выделение блока }
     if H <> 0 then                                         { если память выделена }
     begin
        P := GlobalLock(H);                               { блокировка блока }
        WriteLn(MemAvail,'. Выделено для Вас  ', m-MemAvail,'  байт');
        memw[Seg(p^):Ofs(p^)]:=1234;
                                      { доступ к блоку через указатель, что-нибудь запишем}
        writeLn(memw[Seg(p^):Ofs(p^)]);	{ Теперь прочитаем }
        writeLn(memw[Seg(p^):Ofs(p^)+1]);	{ Что там дальше }

        GlobalUnlock(H);                     { разблокировать блок }
        GlobalFree(H);                        { освободить блок }
     end;
END.

Поэкспериментируйте, установите, сколько памяти на своей ЭВМ Вы сможете получить для программы. Но и вопрос тоже зададим: а запишите что-нибудь по смещению в 1 Мегабайт в эту "Вашу" область
[ в начало ]

© Борис Сурин

Рассылку поддерживает сайт www.turbopascal.tk

При перепечатке ссылка на сайт обязательна

Hosted by uCoz