18. Особенности разработки прикладных информационных систем на основе ПЭВМ

Скачать доклад: 18. Особенности разработки прикладных информационных систем на основе ПЭВМ

Особенности разработки прикладных информационных систем на основе ПЭВМ; структурирование программ на уровне модулей; раздельно компилируемые модули; библиотеки процедур; генерация объектных модулей и загрузочных файлов; библиотеки объектных модулей; реализация сегментированных программ с перекрытиями (4.2.).

При создании прикладного программного обеспечения (ППП) АЭИС на основе ПЭВМ большая часть программных модулей составляется на языках высокого уровня (ЯВУ). Имеется несколько вариантов организации их взаимодействия, основанных на свойствах ЯВУ, и на особенностях операционных систем. Часто возникает необходимость программирования машинно-зависимых частей на языке ассемблера или макроассемблера, в связи с чем встает задача организации взаимодействия программ на ЯВУ с программами на ассемблере.

При проектировании большой АЭИС с самого начало необходимо решать несколько принципиальных вопросов, касающихся общей структуры системы и способов взаимодействия отдельных компонентов. В частности, должны быть определены следующие характеристики: а) состав исходного текста программ, который может представлять собой: единый текст на ЯВУ или ассемблере; отдельные текстовые модули на ЯВУ или ассемблере, которые составляются независимо и, возможно даже разными исполнителями; б) структура исполняемой программы, которая может представлять собой: единый модуль, полностью загружаемый в оперативную память при запуске системы; несколько сегментов, загружаемых в оперативную память по мере необходимости с частичным взаимным перекрытием (наложением друг на друга); резидентную часть, загружаемую в оперативную память в начале сеанса и одну или несколько нерезидентных частей, загружаемых в оперативную память по мере необходимости; в) способ хранения данных, с которыми работает система. Основные варианты хранения: все данные располагаются в одном файле; данные распределены по нескольким файлам.

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

-----------¬ ----------------¬ --------------¬
¦ Редактор +-+текст программы+-+Интерпретатор¦
L----T------ L---------------- L------T-------
¦ ----------------¬ ¦
L-------+ пользователь +---------
L----------------

Структурирование программ на уровне текстовых модулей .. Самый простой способ разработки программ не предполагает применения каких-либо приемов деления их на модули или на сегменты. Для составления такой программы обычно используется текстовый редактор общего назначения или редактор, встроенный в систему.

Процесс разработки программы соответствует общей схеме, изображенной на рисунке.

Простейшая программа на паскале, печатающая на экране слово "АЭИС" может выглядеть следующим образом:

--------------------¬
¦PROGRAM Test; ¦
¦ BEGIN ¦
¦ WRITELN ('АЭИС');¦
¦END. ¦
L--------------------

Более сложные программы включают описания типов данных, переменных констант. Важнейшими компонентами программ на ЯВУ являются процедуры и функции, которые обеспечивают структуризацию программ на уровне исходных текстов. Так, например, общая структура программы на паскале может иметь вид:

---------------------------------------------¬
¦PROGRAM имя-программы (параметры программы) ¦
¦ <описания глобальных объектов программы - ¦
¦ типов данных, переменных, констант> ¦
¦ PROCEDURE P1 (параметры процедуры P1); ¦
¦ <описание локальных объектов процедуры P1>¦
¦ BEGIN ¦
¦ <тело процедуры P1> ¦
¦ END; ¦
¦ PROCEDURE P2 (параметры процедуры P2); ¦
¦ <описание локальных объектов процедуры P2>¦
¦ BEGIN ¦
¦ <тело процедуры P2> ¦
¦ END; ¦
¦............................................¦
¦ BEGIN ¦
¦ <начало тела программы> ¦
¦ ...P1 (...);... {обращение к Р1} ¦
¦ ...P2 (...);... {обращение к Р2} ¦
¦ <конец тела программы> ¦
¦END. ¦
L---------------------------------------------

В этом тексте можно выделить 3 основных компонента:

- заголовок программы - название, список параметров, описания типов, глобальных переменных, констант;

- описания процедур - их заголовки с описаниями параметров и тела,  состоящие из выражений;

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

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

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

---------------------¬
¦{$INCLUDE: 'M1.PAS'}¦
L---------------------

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

Раздельно компилируемые модули .. Если составленная программа велика по объему (содержит от 500 до 100 и более строк), то процесс трансляции может занимать довольно много времени - до нескольких минут, что Неудобно при интенсивной отладке, когда приходится часто вносить небольшие изменения в исходные тексты и вновь транслировать программу. Чтобы этого избежать, применяется другой подход к построению больших программ - составление отдельных модулей, которые транслируются совершенно независимо друг от друга и должны связываться лишь на стадии окончательного формирования исполняемой программы в машинных кодах.

Так, в некоторых реализациях языка паскаль можно использовать два типа раздельно компилируемых модулей: MODULE и UNIT.

------------------------------------¬
¦{----------Модуль P1.PAS----------}¦
¦MODULE P1 ¦
¦PROCEDURE PP1 (A:INTEGER); [PUBLIC]¦
¦ BEGIN ¦
¦ <тело процедуры PP1> ¦
¦ END; ¦
¦PROCEDURE PP2 (B:REAL); [PUBLIC] ¦
¦ BEGIN ¦
¦ <тело процедуры PP2> ¦
¦ END; ¦
¦BEGIN ¦
¦END. ¦
¦{---------------------------------}¦
L------------------------------------

Модуль MODULЕ внешне оформляется почти как главная программа.

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

Описанные в этом модуле процедуры РР1 и РР2 снабжены специальными указателями [PUBLIC], которые свидетельствуют об общедоступности этих процедур для других программ.

Чтобы использовать эти процедуры в главной программе и в других модулях, их необходимо объявить следующим образом:

-------------------------------------¬
¦PROCEDURE PP1 (A:INTEGER); EXTERNAL;¦
¦PROCEDURE PP2 (B:REAL); EXTERNAL; ¦
L-------------------------------------

Указатель EXTERNAL свидетельствует, что объявленные таким образом процедуры являются внешними по отношению к тому модулю, который их использует. Однако обращения к ним в его теле имеют обычный вид, и внешние процедуры не отличаются от тех, которые описаны непосредственно в данном модуле.

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

-----------------------------------¬
¦{----Реализация блока P2.PAS-----}¦
¦IMPLEMENTATION OF P2; ¦
¦ PROCEDURE get_key; ¦
¦ BEGIN ¦
¦ <тело процедуры get_key> ¦
¦ END ¦
¦ <описания и тела других процедур>¦
¦BEGIN END. ¦
L-----------------------------------
------------------------------------------------------¬
¦{----------------------P2.INT-----------------------}¦
¦INTERFACE; ¦
¦ UNIT P2; ¦
¦ (get_key, key_descr,...<имена других процедур>...)¦
¦ TYPE key_descr=RECORD scan_code, ascii:byte end; ¦
¦ PROCEDURE get_key; ¦
¦ ..... ¦
¦ <заголовки других процедур данного блока> ¦
¦ ..... ¦
¦END; ¦
¦{---------------------------------------------------}¦
L------------------------------------------------------

Библиотеки процедур .. Модуль типа UNIT, который можно назвать иначе "блоком", описывается с помощью следующих компонентов. Один из них (реализация блока) содержит тела процедур и вспомогательные типы, переменные и константы. Другой компонент - описание  блока или интерфейс - содержит описания типов, переменных и констант, а также заголовки процедур (без их тел), которые предназначены для использования в других модулях и в главной программе.

В интерфейс блока включается общий список имен, указанных объектов, что делает их "видимыми" из других модулей.

----------------------------¬
¦{----Главная программа----}¦
¦{$INCLUDE: 'P2.INT'} ¦
¦..... ¦
¦PROGRAM PP (input, output);¦
¦ USES P2; ¦
¦..... ¦
¦{-------------------------}¦
L----------------------------

Использование объектов модуля типа UNIT в главной программе требует включения включения его интерфейса перед заголовком программы, и упоминания имени блока сразу после заголовка программы, для чего служит выражение вида: USES <имя блока>;

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

Здесь текстовое включение интерфейса блока Р2 в программу РР.PAS осуществляется с помошью рассмотренного выше выражения $INCLUDE.

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

  -----------¬
¦ PAS1 PP; ¦
¦ PAS2 ¦
L-----------

Объектный модуль, который порождается после двух проходов трансляции (PAS1 и PAS2), можно счи- тать "полуфабрикатом" - куском машинного кода, го- товым к превращению в  _загрузочный файл .. Объектный модуль заносится в особый файл, которому придается тип OBJ. Для рассматриваемого примера этот процесс можно изобразить следующей условной схемой: PP.PAS --- транслятор --- PP.OBJ

Следующий этап состоит в преобразовании совокупности отдельных объектных модулей в загрузочный файл типа ЕХЕ или СОМ. Этот процесс называется связыванием объектных модулей или сборкой задачи .. Соответствующая схема преобразования: РР.ОВJ --- PP.EXE или PP.OBJ --- PP.COM

Этот этап реализуется специальной системной программой LINK, которую называют редактором связей или  компоновщиком .. При обращении к LINK указываются все объектные модули, которые должны объединены в общую программу; указывается также имя файла с результирующей программой, имя файла с листингом (необязательный параметр) и имя файла с библиотекой процедур:

LINK PP+P1+P2 ., PP ., PP.LST ., PASLIB.LIB объектные загрузоч- файл- библиотека модули ный файл листинг процедур

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

LIB <старая-библиотека> <размер-страницы> <операции>

<файл-с-листингом> <новая-библиотека>

При обращении к LIB могут указываться имена старой и новой библиотеки. Размер страницы (=16, 32 ... 512) задает величину буфера для обмена; это необязательный параметр. Главные действия задаются операциями. Операция может иметь следующие разновидности (mm - имя модуля):

+ mm {добавление модуля в библиотеку},
- mm {удаление модуля из библиотеки},
* mm {извлечение модуля из библиотеки},
-+ mm {замена модуля в библиотеке},
-* mm {извлечение модуля с удалением},

Пример обращения к LIB: LIB OLDLIB+P2, ,NEWLIB

Такое обращение вызывает создание новой библиотеки NEWLIB из старой OLDLIB c добавлением отдельно оттранслированного модуля Р2. После того, как библиотека создана, достаточно упомянуть ее имя при связывании объектных модулей в единую программу.

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

Процесс трансляции складывается из стадий: формирование текстовых модулей (с использованием текстовой подстановки); синтаксический анализ и выдача ошибок, найденных транслятором в тексте программы; генерация объектных модулей в машинных кодах, оптимизация; сборка из объектных модулей исполняемого кода программы.

Эти приемы позволяют при составлении исходных текстов программ иметь дело с несколькими автономными компонентами, которые собираются вместе в начале процесса трансляции (текстовое включение), или при сборке исполняемых программ (использование раздельно компилируемых модулей и библиотек процедур). Благодаря такому методу программы становятся удобными для анализа и модификации.

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

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

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

В развитой системе программирования, базирующейся на ЯВУ типа паскаль, распространенным приемом такого деления программ на части основан на создании перекрывающихся (оверлейных) сегментов, при котором программа составляется из отдельных кусков, (во время работы они могут по мере необходимости загружаться в оперативную память и частично накладываться друг на друга.

---------------------------¬
¦PROGRAM PP (input,output);¦
¦....... ¦
¦ OVERLAY PROCEDURE P1; ¦
¦ BEGIN ¦
¦ <тело процедуры P1> ¦
¦ END; ¦
¦ OVERLAY PROCEDURE P2; ¦
¦ BEGIN ¦
¦ <тело процедуры P2> ¦
¦ END; ¦
¦ PROCEDURE P3; ¦
¦ BEGIN ¦
¦ <тело процедуры P3> ¦
¦ END; ¦
¦ OVERLAY PROCEDURE P4; ¦
¦ BEGIN ¦
¦ <тело процедуры P4> ¦
¦ END; ¦
¦ ........ ¦
¦ BEGIN ¦
¦ <P1> ¦
¦ END. ¦
L---------------------------

Сегменты хранятся во внешней памяти (на диске) и лишь один из них - корневой - находится постоянно в оперативной памяти.

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

Пример объявления оверлейных процедур, тела которых после трансляции попадают в соответствующие оверлейные файлы, приведен на схеме.

Трансляция такой программы приведет к созданию трех перекрывающихся сегментов: РР.СОМ РР.000 РР.001

Первый из них - РР.СОМ - соответствует главной программе, два других сегмента - оверлейные. При этом процедуры Р1 и Р2 попадут в сегмент РР.000, поскольку в исходном тексте их описания следуют одно за другим. Процедура Р4 окажется во втором оверлейном сегменте - РР.

001. Такое разделение обусловлено тем, что описание Р4 отделено от описаний двух первых процедур внутренней (не оверлейной) процедурой Р3. Получившаяся структура программы может быть отображена схемой, представленной на на рисунке:

  Корневой сегмент РР.СОМ      Оверлейный сегмент РР.000
-----------------------¬ ------------------------¬
¦ код программы ¦ ---+ код процедуры Р1 ¦
+----------------------+ ¦ +-----------------------+
¦ ¦ +--+ код процедуры Р2 ¦
¦область для оверлейных+---- L------------------------
¦сегментов +---¬
¦ ¦ ¦ Оверлейный сегмент РР.001
+----------------------+ ¦ ------------------------¬
¦ код программы ¦ L--+ код процедуры Р4 ¦
L----------------------- L------------------------