Содержание                
 

Оверлей

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

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

Пусть, например, программа состоит из главной части МАIN и двух модулей А и В. Пусть также LМ, LА и LВ - длина соответственно главной части и обоих модулей, причем LA > LВ. Тогда неоверлейная программа займет в памяти LМ + LA + LВ байт, в то время как оверлейная программа лишь LМ + LА.

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

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

Работа оверлейных программ обеспечивается с помощью процедур, и функций библиотечного модуля OVERLAY, входящего в библиотечный файл TURBO.TPL.

Оверлейные программы нужно создавать в такой последовательности:

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

  • В главной части программы необходимо указать с помощью директив компилятора вида {$0 < имя >} те модули, которые будут оверлейными, например:
    Program Main;
    Uses CRT, DOS, Graph, Overlay, UnitA, UnitB;
    {$O DOS}
    {$O UNITA}
    {$O UNITB}
    Учтите, что из всех стандартных библиотечных модулей только модуль DOS может быть оверлейным, остальные же модули (CRT, Graph, Printer и т.д.) не могут объявляться оверлейными.

  • Необходимо предусмотреть перед первым по логике работы программы обращением к какому-либо оверлейному модулю вызов процедуры инициализации оверлея OVERINIT. Здесь же, если это необходимо, следует установить размер оверлейного буфера и указать возможность использования расширенной памяти (см. ниже).

  • Наконец, в начале главной программы и каждого оверлейного модуля необходимо поместить директивы компилятора {$O+} и {$F+} или установить опции OPTIONS/COMPILE/FORCE FAR CALLS и OPTIONS/COMPILE/OVERLAYS ALLOWED в состояние ОN, после чего следует откомпилировать программу на диск. Программа готова к работе.

  • Необходимо использовать дальнюю модель вызова - это обязательное условие.

Директива {$O+}, строго говоря, не является обязательной. Если она указана, то при вызове любой процедуры или функции программа будет помещать все фактические параметры обращения в резидентную (неоверлейную) часть памяти, что позволяет из одного оверлейного модуля вызывать процедуры и функции любого другого оверлейного же модуля.

Процедура OVRINIT. Инициализирует оверлейный файл; формат обращения OVRINIT(< имя >)
Здесь < имя > - выражение типа STRING, означающее имя файла с оверлейной частью программы.

При компиляции оверлейной программы создается специальный файл с именем, совпадающим с именем главной программы, и расширением .OVR. В этот файл компилятор помещает все оверлейные модули, из него же эти модули будут загружаться в оверлейный буфер в процессе исполнения программы. Файл с оверлейной частью программы должен размещаться в том же каталоге, что и файл с главной частью (с расширением .ЕХЕ).

Пример: пусть файл с главной частью программы называется MAIN.РАS, в программе используются два оверлейных модуля, помещаемые в файлы UNITA.PAS и UNITB.PAS.

Program OverlayDemo; {Текст главной программы нужно поместить в файл МAIN.РАS.}
{$F+,0+}
Uses Over1ay, UnitA, UnitB;
{$0 UnitA}
{$0 UnitB}
Begin
 OvrInit('MAIN.OVR');
 SubA
End.
{---------------------------------------------------------------}
UNIT UnitA; {Текст модуля нужно поместить в файл UNITA.PAS}
{$F+,0+}
Interface
Uses UnitB;
 Procedure SubA;
Implementation
 Procedure SubA;
 const
  st = 'Работает модуль’;
 Begin
  Writeln(st, 'A');
  SubB(st);
 End;
End.
{---------------------------------------------------------------}
Unit UnitB; {Текст модуля нумно поместить в файл UNITB.PAS.}
{$F+,0+}
Interface
 Procedure SubB(s: string);
Implementation
 Procedure SubB;
 Begin
  Writeln(s, 'B');
 End;
End.

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

Процедура OVRSETBUF. Устанавливает больший, чем по умолчанию, размер оверлейного буфера; формат обращения OVRSETBUF(< длина >)
Здесь < длина > - выражение типа LONGINT, определяющее новую длину буфера.

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

Функция OVRGETBUF. Возвращает значение типа LONGINT, содержащее текущий размер кучи. Обращение OVRGETBUF.

Если Ваша ЭВМ имеет расширенную память (общий объем памяти свыше 1024 Кбайт), Вы можете использовать эту память для размещения в ней оверлейного файла .ОVR. Поскольку время доступа к расширенной памяти значительно меньше времени чтения с диска, такое размещение увеличивает скорость исполнения оверлейной программы.

Процедура OVRINITEMS обеспечивает использование расширенной памяти.
Обращение OVRINITEMS
При обращении к этой процедуре программа прежде всего проверит, подключена ли к Вашей ЭВМ ЕМS-память (от англ. Expanded Memory Specification - расширенная память,) нужного для размещения оверлейной части объема. Если это так, то оверлейный файл будет считан в расширенную память, сам файл будет закрыт и программа будет считывать оверлейные модули из этой памяти. Если же расширенная память отсутствует или ее объем недостаточен для размещения оверлейного файла, обращение к процедуре игнорируется и программа будет считывать оверлейные модули с диска.