355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Фрэнк Солтис » Основы AS/400 » Текст книги (страница 11)
Основы AS/400
  • Текст добавлен: 26 сентября 2016, 19:20

Текст книги "Основы AS/400"


Автор книги: Фрэнк Солтис


Жанр:

   

ОС и Сети


сообщить о нарушении

Текущая страница: 11 (всего у книги 41 страниц)

Неисполняемый интерфейс

Команды MI не исполняются аппаратурой непосредственно. Они либо предварительно (до исполнения программы) транслируются в аппаратный набор команд, либо специальный компонент SLIC интерпретирует некоторые команды MI одну за другой. Пример интерпретируемых команд MI – API Advanced 36. Мы называем процесс преобразования команд MI в низкоуровневые аппаратные команды трансляцией, а не компиляцией, так как при этом выполняется лишь часть функций компиляции. Прежде результатом такой трансляции был набор инструкций IMPI – теперь это набор инструкций PowerPC.

Набор инструкций MI нельзя считать ЯВУ в обычном смысле. Правильнее рассматривать его как разновидность промежуточного представления программы в современном компиляторе ЯВУ. Кое-кто предпочитает представлять набор инструкций MI как ЯВУ, требующий трансляции на более низкий уровень или исполнения посредством интерпретации. Краткое описание оптимизирующих компиляторов поможет понять, почему MI лучше рассматривать как промежуточное звено.

Структура современного оптимизирующего компилятора показана на рис. 4.1. Обычно, компилятор состоит из двух и более проходов или фаз. Проход – это одна фаза, за которую компилятор считывает и модифицирует всю программу. Термины фаза и проход часто используются как синонимы.

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

Возможности однопроходного компилятора по оптимизации ограничены. Проще говоря, он не может просмотреть код программы вперед и учесть то, что произойдет дальше. «Заглянуть вперед» может многопроходный компилятор. Назначение регистров переменным в зависимости от их связей с другими переменными, запись в память ненужного более содержимого кэша, предварительная выборка операндов – вот лишь некоторые примеры оптимизации, выполняемой многопроходным компилятором.

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

Рисунок 4.1 Структура оптимизирующего компилятора

Первый проход компилятора, показанного на рис. 4.1, часто называют препроцессором (front end) компилятора. Его задача – преобразование текста на ЯВУ в общую промежуточную форму (common intermediate form).

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

Набор команд MI аналогичен общей промежуточной форме, применяемой в компиляторах. Компилятор ЯВУ преобразует исходный текст в форму для MI. Транслятор, расположенный уровнем ниже MI, считывает программу в этой форме, выполняет оптимизацию и генерирует инструкции IMPI или PowerPC. Транслятор очень напоминает постпроцессор компилятора.

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

Набор инструкций MI заменяет общую промежуточную форму не во всех компиляторах AS/400 – некоторые языки имеют собственную промежуточную форму. Ниже приводится описание внутренней структуры компиляторов языков для AS/400, и место MI в этой структуре.

Компиляторы для AS/400

Ранние компиляторы (например, RPG/400 и языка управления CL) для System/38 и AS/400 генерировали команды: MI довольно прямолинейно. Хотя они и проходили уровень ассемблера, в самом компиляторе не было общей промежуточной формы. Ее роль выполняли команды MI.

Модель программы для этих языков, включая форму программы ниже уровня MI, называется исходной моделью программ или OPM (Original Program Model). Позднее, для языков типа C/400, была добавлена расширенная модель программ или EPM (Extended Program Model). На рисунке 4.2 показан процесс генерации кода IMPI для OPM и ЕРМ. Мы представили здесь эти две модели только для демонстрации эволюции компиляторов AS/400. На RISC-системах версии 4 не используются ни компиляторы ОРМ, ни ЕРМ.

Сначала рассмотрим компилятор ОРМ. Он принимает на входе операторы ЯВУ ОРМ (вместе с не показанными на рисунке описаниями файлов) и на выходе генерирует код промежуточного представления программы IRP (Intermediate Representation of a Program). IRP, по сути, – ассемблер для команд MI. Следующий шаг – код IRP преобразуется в команды MI с помощью компонента под названием PRM (Program Resolution Monitor), который создает шаблон программы, помеченный на рисунке как шаблон программы ОРМ и содержащий команды MI и другие данные. Шаблоны используются для создания объектов MI. Транслятор, расположенный ниже уровня MI, создает по шаблону программы программный объект, содержащий команды IMPI. Содержание шаблона программы будет рассмотрено далее.

ОРМ – пример классического компилятора, генерирующего ассемблерную форму программы (IRP), после чего ассемблер (PRM) генерирует двоичную машинную программу (шаблон программы). Компиляция на AS/400 требует дополнительного шага (этапа трансляции) и поэтому может занимать больше времени, чем на некоторых других системах. Обратите внимание, что все эти этапы для пользователя AS/400 невидимы и выглядят, как одна операция.

По мере реализации на AS/400 новых языков, таких как С/400 и Pascal, потребовалось добавить расширения. Этапы компиляции для ЕРМ (расширенной версии ОРМ) также показаны на рис. 4.2. В компиляторах таких языков препроцессор и постпроцессор разделены. Общая промежуточная форма в них называется U-код. Для AS/400 был создан новый постпроцессор компиляторов CUBE-1 (Common Use Back End 1).

Рисунок 4.2 Компиляторы ОРМ и ЕРМ

Для повышения производительности модульного программирования и стимуляции его распространения на все языки, были внесены архитектурные расширения в MI и объекты, расположенные ниже. Эта модификация датирована 1993 годом и называется ILE (Integrated Language Environment). В состав ILE входят новые компиляторы ЯВУ, новый оптимизирующий транслятор (OX) и новые средства связи для создания многомодульных программ[ 35 ]35
  Оптимизирующий транслятор, известный под названием ОХ, был создан совместно Рочесте-ром и исследовательской лабораторией IBM в Хайфе (Haifa), где накоплен большой опыт разработки машинно-зависимых приемов компиляции для конвейерных суперскалярных процессоров. В Хайфе было создано несколько компонентов ОХ.


[Закрыть]
. ILE изменил программирование. В отличие от ОРМ, на выходе у этого транслятора не программный объект, а модуль. Средство связывания ILE компонует эти модули в программы.

Кроме поддержки вызовов с поздней компоновкой ОРМ, в ILE есть возможность компоновки во время компиляции. Преимущество такой ранней компоновки состо-

ит в сокращении накладных расходов, связанных с внешними динамическими вызовами. Заранее скомпонованные или статические вызовы выполняются быстрее.

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

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

Модуль – объект, содержащий код, полученный на выходе компилятора ILE. В отличие от программы, создаваемой компилятором OPM, модуль не исполняем. Модуль может содержать одну или несколько процедур. Компоновщик ILE собирает программы и служебные программы из модулей, возможно, написанных на разных языках.

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

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

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

Деление на программы и служебные программы связано с необходимостью поддержки двух типов статических вызовов: связь через копию (bound by copy) и связь через ссылку (bound by reference). Первые позволяют копировать в программу одновременно несколько модулей. Как мы только что говорили, сама программа вызывается динамически, но после этого вызовы процедур из всех модулей происходят статически. Так как имена процедур преобразуются в адреса во время компиляции, данный тип статического вызова внутри программы выполняется быстрее, чем динамический вызов. Недостаток связи через копирование в том, что в памяти может одновременно находиться несколько копий модуля, если он связан с несколькими программами. За все нужно платить, и здесь за быстродействие мы расплачиваемся дополнительным расходом памяти.

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

В обоих методах ранней компоновки используется новая команда вызов связанной процедуры CALLB (call bound procedure). Другая новая команда, вызов программы или CALLPGM (call program) поддерживает позднее связывание и заменяет команду вызова внешней процедуры ОРМ.

Структура компиляторов программной модели ILE показана на рис. 4.3.

Рисунок 4.3 Компилятор программной модели ILE

Препроцессор компилятора ILE генерирует общую промежуточную форму – W-код. Постпроцессор таких компиляторов называется CUBE-3. Цифрой 3 обозначено третье и самое последнее поколение технологии компиляторов IBM. CUBE-3 и W-код спроектированы с учетом эффективной поддержки RISC-процессоров.

Другие системы IBM, в частности RS/6000, используют те же технологии. Постпроцессор компилятора ILE генерирует непосредственно шаблон программы ILE, устраняя IRP и шаг PRM. Чтобы обеспечить необходимую оптимизацию RISC-процессоров, в MI добавлены арифметические команды и команды переходов в стиле W-кода, которые мы рассмотрим далее.

Модель ILE – единственная программная модель для RISC-процессоров – является расширением архитектуры MI. На системах IMPI программные модели ILE и ОРМ/ЕРМ сосуществуют, так что на одном и том же компьютере может использоваться и код, сгенерированный старыми компиляторами, и сами компиляторы.

Рисунок 4.4 Компиляторы ОРМ и ЕРМ на V4 RISC

Перенос программы ОРМ/ЕРМ на систему RISC вызывает ее внутреннее преобразование в программную модель ILE. На рис. 4.4 показаны шаги компиляции ОРМ или ЕРМ для системы RISC версии 4. Для использования старых компиляторов на новых RISC-моделях нужен дополнительный шаг: результат работы таких компиляторов – шаблон оригинального MI – должен быть преобразован в шаблон ILE MI. Компонент, выполняющий данное преобразование, называется Magic, (намек на то, что преобразование происходит как бы магическим образом).

Рисунок 4.4 Компиляторы ОРМ и ЕРМ на V4 RISC

Характеристики машинного интерфейса

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

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

Рисунок 4.5 Обычный машинный интерфейс

Обычные машинные интерфейсы работают с содержимым регистров, памяти или непосредственно с данными, записанными в самой команде. Иначе говоря, они «не подозревают» о данных приложения или операционной системы. Возьмем стандартную команду «регистровое сложение». Она задает два регистра процессора и выполняет операцию, извлекая биты из одного регистра, складывая их с битами из другого регистра и помещая результат в определенное место. Смысла этих битов команда «не понимает» —о нем «заботится» программа. Для машины это просто набор битов, к которому применяется алгоритм сложения. То, что в регистрах находятся, например, имена двух сотрудников и поэтому рассматривать их в качестве арифметических операндов нет смысла, никого не волнует. Операции этого уровня просто механически обрабатывают содержимое регистров или памяти.

Мы уже говорили о недостатке такой структуры – ее существенной зависимости от аппаратной технологии. Так как команды: работают в адресном пространстве, с областями ввода/вывода и регистрами, они привязаны к этим физическим структурам. Изменение последних может потребовать изменения команд. Значит, преобразование существующих программ может вызвать существенные проблемы.

Рисунок 4.6 Машинный интерфейс AS/400

Машинный интерфейс AS/400 (см. рисунок 4.6) устроен совсем иначе. У него, как и у обычных, есть набор команд с кодами операций и операндами. Есть в нем и разные типы арифметических операций (например, команды: сложения) и операций передачи управления, работающие с традиционными операндами. Но в отличие от обычного интерфейса в нем есть команды, аналогичные промежуточному представлению, используемому в современных компиляторах ЯВУ, а также структуры данных (объекты).

Самое важное отличие не в самих командах или операциях, а в используемых ими операндах. В обычном интерфейсе есть регистры, память и непосредственные данные. На AS/400 мы по-прежнему имеем непосредственные данные, но нет ни регистров, ни памяти. Их заменяют объекты.

В MI определены объекты нескольких типов. Большинство из них – сложные структуры данных, нужные для представления информационных ресурсов. Один из самых важных типов объектов в системе – пространство (просто набор байтов, не связанный с физическим оборудованием). Многие с трудом представляют себе массу подвешенных неизвестно где байтов, им хочется обязательно связать их с аппаратурой. Но в MI понятие пространства не имеет отношения к физической памяти, он абсолютно независим от того, что находится ниже[ 36 ]36
  Специалисты по AS/400 любят рассуждать об одноуровневой памяти. Как мы только что убедились, в MI вообще нет памяти. Таким образом, одноуровневая память невидима или находится вне MI; скорее, это часть внутренней реализации AS/400.


[Закрыть]
.

Когда программе MI требуется память, она использует пространство. На этом уровне нет понятий регистров, физической памяти и адресов памяти в традиционном смысле. Например, компилятор AS/400 должен куда-то деть созданный шаблон программы – в пространство!

Кроме пространств, существуют и другие типы объектов, которые мы обсудим далее. До сих пор мы обсуждали только системные объекты MI. Но объекты поддерживает и OS/400.

Работа с программами MI

Несколько команд MI работают с программами. Так как программа представляет собой объект, эти команды: рассматривают программу целиком. Все команды выполняют над программой только операции, имеющие смысл. Есть команда создания программы, но нет команды перемножения программ, так как первая имеет смысл, а вторая – нет. Короче, команды специфичны для объектов того типа, с которым они манипулируют. Команды применяются к объекту целиком, а не к некоторым частям данных внутри объекта. Объект нельзя использовать не по назначению, так что еще одно крупное преимущество объектной ориентации – целостность. Программы в MI играют только присущую им роль. Давайте рассмотрим, как программа создается, уничтожается и материализуется.

Создание программы

Программа создается на основе шаблона – заранее описанной структуры со всеми характеристиками определенного системного объекта MI. Шаблон формируется частью компилятора AS/400, отвечающей за генерацию кода. Все системные объекты MI образуются по шаблонам, хранящимся в пространствах MI. Так как объектам разного типа присущи разные характеристики, единого общего шаблона нет – у каждого объекта свой уникальный шаблон.

Команда создания программы «Create Program» указывает на шаблон программы. Пока мы остановимся на двух типах указателей: системном и пространственном (позже мы увидим, что есть указатели и других типов). Первый направлен на системный объект MI, второй – на байт в пространстве. Длина каждого из этих указателей 16 байт. Через указатели в MI осуществляется адресация, так что указатель в MI можно представлять себе просто как адрес.

Команда создания программы исполняется с помощью кода, лежащего ниже MI. Сначала через пространственный указатель команды «Create Program» код находит шаблон программы, над которым выполняется синтаксический контроль. Затем транслятор преобразует последовательность команд MI-шаблона программы в последовательность внутренних команд IMPI или PowerPC, которая упаковывается в системный объект MI – программу. Наконец, инициатору запроса возвращается адрес вновь созданной программы в виде системного указателя на этот объект. Если в какой-то части данной операции возникают проблемы, соответствующая диагностическая информация возвращается в виде сообщения.

Уничтожение программы

Любой объект на уровне MI, который можно создать, можно и уничтожить. Соответственно на каждую команду создания объектов MI приходится команда уничтожения. Пользователь на уровне MI устанавливает системный указатель на программу или другой объект MI и дает команду: «Уничтожить». Конечно, сделать это просто так нельзя: у пользователя должны быть соответствующие права на доступ к разным объектам.

Тему прав пользователей по отношению к объектам мы подробно обсудим в главе 7, а сейчас только упомянем, что пользователь может иметь разные уровни прав доступа к разным объектам. Чтобы уничтожать объекты, нужен самый высокий уровень. Как правило, объект может уничтожить только его владелец; но бывают ситуации, когда такие права имеют несколько пользователей. Каждому пользователю в системе соответствует специальный объект – профиль пользователя. Вместе с другими объектами профиль пользователя определяет права данного пользователя по отношению к тем или иным объектам. Когда пользователь прибегает к команде уничтожения, система сначала обращается к его профилю и выясняет, есть ли у него такое право, и лишь в случае утвердительного ответа выполняет операцию.

Материализация и адаптируемость программы

Наблюдать характеристики программы поверх MI можно лишь через шаблон программы. Шаблон – результат работы компиляторов ЯВУ. Это самый нижний уровень, на котором возможна работа с компонентами программы поверх MI. Ниже MI программа существует в виде системного объекта, и все работающие с ним команды MI воспринимают его как единое целое.

Внутри объекта находится последовательность команд IMPI или PowerPC. Объект инкапсулирован, то есть, невидим извне. Это обеспечивает независимость от технологии, однако программа не имеет законченной формы, так как последовательность ее команд невидима.

Однако, если прикладному или системному ПО необходим доступ к характеристикам программы, команда MI, позволяет эту программу материализовать. Команда материализации указывает на инкапсулированный программный объект, по которому воссоздается шаблон программы. Материализация – операция, противоположная инкапсуляции.

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

Как же решает эту задачу AS/400? Да просто жульничает: она не выполняет де-компиляции последовательности команд IMPI или PowerPC. Вместо этого копия шаблона программы сохраняется вместе с объектом. Когда выполняется команда MI материализующая программу, в ответ возвращается объект шаблона программы.

Хранение шаблона программы в качестве системного объекта MI и придает System/38 и AS/400 возможности, отсутствующие в других системах. Это позволяет изменять набор команд, не влияя на приложения заказчиков. Изменения вносятся в новую версию транслятора, а затем все программы ретранслируются из своих шаблонов. Наконец, новые последовательности команд снова инкапсулируются в объекты. Все это происходит ниже MI и без участия пользователя.

Чтобы Вы смогли лучше «почувствовать разницу», обратимся к классическому примеру внедрения System/38 Model 7. System/38 появилась как абсолютно новая система с абсолютно новым набором команд, новыми приложениями и новой ОС. Но как использовать эти команды:, никто точно не знал. Как правило, для того, чтобы достичь максимальной производительности системы, оптимизируют аппаратную реализацию наиболее часто встречающихся последовательностей команд с целью достичь их как можно более быстрого выполнения.

Первоначально набор команд IMPI имел только 8-битные коды операций, то есть команд не могло быть более 256 (28 = 25 6). Когда начали писать приложения для System/38, то обнаружилось, что нужны новые функции. В ответ мы изобретали новые команды (своего рода болезнь!) и очень скоро вышли за эти пределы.

Вполне естественно стремление сохранить набор операций небольшим, а следовательно, контролируемым и не избыточным. Но не менее законно желание упростить сложные задачи. Как увязать эти противоречия? Хорошо, если б существовал научный метод создания наборов команд, но, увы! Это скорее искусство, чем наука. Через пару лет мы пришли, как нам казалось, к оптимальному набору команд IMPI. И чтобы добавить эти новые команды, решили ввести в формат команд IMPI расширения кода операции.

К тому времени мы уже знали, как работать с существующими командами IMPI и как повысить производительность путем перевода наиболее часто используемых команд в другие, более быстрые форматы. Изменение кодов операций означает, что команда, на предыдущей версии оборудования вызывавшая, скажем, загрузку, на новой версии служит для передачи управления. В любой «нормальной» системе такая замена привела бы к хаосу, но не в System/38 – ведь она не зависит от технологии.

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

Это работало блестяще, но... начались претензии заказчиков: «Я только что °—° установил систему, и мне кажется, что прикладные программы стали работать медленнее». Это и понятно: ретрансляция впервые запущенного приложения приводила к замедлению работы. Как Вы думаете, что мы отвечали? Конечно же – «Попробуйте еще раз». Тот же метод скрытой ретрансляции программ применялся при переходе на RISC-процессоры. Разница была лишь в том, что заказчиков заранее предупреждали, что приложения будут работать, только если не удалена адаптируемость. Что же изменилось со времен System/38?

AS/400 должна была привлечь и пользователей System/36, и System/38. Между тем вторые привыкли к большим объемам памяти и жестких дисков, так же как и пользователи System/36 – обходиться малым. Поэтому размеры новых программ последних пугали, и казались им чересчур большими.

Программы для AS/400 действительно впечатляли – ведь каждая хранилась в двух копиях: в инкапсулированной форме и в форме шаблона. Для экономии пространства на диске заказчики могли удалить шаблоны. Это называлось удалением адаптируемости программы (Delete Program Observability), так как после программу уже нельзя было материализовать.

В результате те, кто удалил адаптируемость некоторых или всех своих программ, должны были вернуться к исходным текстам на ЯВУ и заново откомпилировать их, прежде чем переносить на RISC-процессоры. И хотя на AS/400 это все равно проще, чем на большинстве других систем, все же перенос не выполнялся автоматически, как при наличии программного шаблона.


    Ваша оценка произведения:

Популярные книги за неделю