Текст книги "Основы AS/400"
Автор книги: Фрэнк Солтис
Жанр:
ОС и Сети
сообщить о нарушении
Текущая страница: 4 (всего у книги 41 страниц)
Создание программ
Программное обеспечение любой вычислительной системы можно условно разделить на два типа: системное и прикладное. Примеры системного программного обеспечения – операционные системы, ассемблеры и компиляторы. Прикладное же программное обеспечение обычно предназначается непосредственно для пользователей и решает конкретные задачи.
Ранее считалось, что доступ к архитектуре самого нижнего уровня посредством ассемблера необходим как системному, так и прикладному программисту. В пользу этого суждения приводилось множество аргументов: большинство программ имели доступ к крайне незначительному объему памяти, процессоры были медленными и дорогими, а компиляторы с языков высокого уровня – не слишком хорошими. Когда нужно было «выжать последний грамм» для повышения производительности компьютера, «настоящие» программисты использовали язык ассемблера.
Теперь же появилось много приверженцев мнения, что программирование на языке ассемблера – реликт прошлого. Но это не так. Большинство используемых ныне операционных систем (не только старых, чьи корни которых восходят к 60-м и началу 70-х годов, но и более современных) включают в себя большие объемы кода на ассемблере. Таковы, например, операционные системы для ПК: Windows 95 фирмы Microsoft написана по большей части на языке ассемблера Intel.
Первые процессоры для ПК имели достаточно ограниченные возможности. Максимальный размер памяти был равен 64 килобайтам. (Один килобайт равен 210 или 1024 байтам. Байт – это 8-разрядная ячейка памяти, в которой может храниться символ или цифра). Память стоила настолько дорого, что операционные системы могли занимать не более 4 килобайт. Язык ассемблера позволял программистам максимально сокращать размер кода. В результате на нем написан такой большой объем операционных систем, что даже когда размер доступной памяти увеличился благодаря удешевлению технологии, возвращаться назад и переписывать оригинальный код оказалось непрактичным.
Использование ассемблера действительно позволяет оптимизировать размеры и производительность программ. Тем не менее, у этой технологии, по крайней мере, один существенный недостаток: все программы напрямую привязаны к аппаратуре. Любое ее изменение может вызвать необходимость переписать некоторые или даже все программы.
В качестве примера такой ситуации рассмотрим компьютер, имеющий восемь регистров. Регистр – часть тракта данных процессора. Это быстродействующая область памяти, куда помещаются данные и адреса на время их использования процессором. Основное назначение регистров – повышение производительности работы программ. Предположим, что ширина каждого регистра – 16 разрядов, и что программист может помещать данные в регистры и выбирать их оттуда в любой момент по своему усмотрению. Число регистров и их характеристики программист видит из ассемблера. Таким образом, каждая программа для данного компьютера, написанная на этом языке, будет «знать» о восьми регистрах и зависеть от них.
Теперь предположим, что технологический прогресс позволил конструкторам увеличить количество регистров до 16 и сделать их 32-разрядными, причем стоит все это столько же, сколько и оригинальные 8 регистров меньшего размера. Зададимся вопросом: «Как это повлияет на программы, написанные для старого компьютера?». Ответ зависит от того, каким образом были сделаны изменения, и сколь хорошо первоначальная архитектура была спланирована для расширения в будущем.
Допустим, что в старой архитектуре предполагалось расширение до 16 регистров. В каждой команде было зарезервировано достаточно места для адресации 16 регистров, хотя первоначально были реализованы только 8. Для каждой команды, использующей регистры, в данном случае понадобились бы 4-разрядные поля, так как 4 бита позволяют закодировать 16 различных комбинаций нулей и единиц. На новом оборудовании старые программы могут выполняться без изменений. При этом они по-прежнему будут использовать только 8 регистров, новые же программы смогут воспользоваться всеми 16-ю.
А теперь представим себе вместо этого, что в старой архитектуре не были учтены будущие изменения и место для расширения не зарезервировано. Тогда новая архитектура не сможет увеличить количество регистров, не изменив при этом каждую команду, которая их использует. Невозможно растянуть трехбитовые поля в командах до 4 бит, не затронув при этом в той или иной степени существующие программы.
Одна из многих архитектур, неспособных увеличить число пользовательских регистров, – Intel Pentium Pro. Она использует то же количество регистров, что и ее предшественник Intel 386. Хотя увеличение числа регистров дало бы Pentium Pro преимущества, но затраты на переписывание существующих ассемблерных программ слишком велики.
Вообще, увеличение размера регистров с 16 до 32 разрядов оказывает меньшее влияние, чем изменение их количества. Если увеличился только размер, то старые программы будут по-прежнему работать, но использовать лишь 16 из 32 разрядов новых регистров. Данная информация внедрена в логику программы, и ее трудно изменить[ 7 ]7
На самом деле все гораздо хуже – некоторые программы явно рассчитывают на 16-разрядную адресацию. Например в них сильно изменяются условия возникновения переполнения при выполнении арифметических операций в регистрах и т. д. Очевидно, что такого рода зависимости не проявляются сразу после перехода с 16-ти на 32-х разрядные процессоры (регистры) и в результате появляются «плавающие» ошибки, которые очень трудно обнаружить.—Прим. консультанта.
[Закрыть].
И подобных примеров, когда широко применяемые программы не способны использовать все ресурсы оборудования, – несметное множество. Процессор Intel 386, появившийся еще в 1985 году, имел 32-разрядный дизайн, то есть размер его аппаратных регистров был равен 32 битам. С того времени все процессоры Intel, включая 486, Pentium, Pentium II и Pentium Pro – 32-разрядные. Однако и большинство программ для ПК, использующих эти процессоры, и операционная система DOS были созданы в те времена, когда был доступен только 16-разрядный процессор Intel 286. Даже операционная система Windows 95 написана в основном на 16-разрядном ассемблере. На переписывание прикладных и системных программ ПК под 32-разрядную аппаратуру ушло уже 12 лет, и процесс все еще не завершен.
Эта проблема не ограничивается только индустрией ПК. Прогресс аппаратных технологий поднял планку еще выше: большинство новых процессоров будут 64-разрядными. Чтобы воспользоваться этим более мощным оборудованием, большинство современных 32-разрядных операционных систем и 32-разрядных прикладных программ должны быть переписаны. А это опять долгие годы работы.
В рассмотренных выше примерах модификации аппаратуры состояли в изменении размера и числа регистров процессора. Учтите, что аналогичное влияние на программное обеспечение, написанное на ассемблере, могут оказать и изменения в структуре адресации процессора или в самом наборе команд.
Основная цель программирования только на языках высокого уровня – минимизировать изменения в программах, вызываемые подобными модификациями аппаратуры. К сожалению, в системном программном обеспечении явно наблюдается тенденция перехода на языки, подобные С и С++. Использование С позволяет повысить переносимость системного программного обеспечения, так как компиляторы для этого языка есть на многих аппаратных платформах, но не устраняет все сложности, связанные с изменениями в оборудовании. Некоторые аппаратные характеристики, например разрядность процессора, видимы программисту на С. Такая возможность доступа к внутренним характеристикам привлекательна для системных программистов и объясняет популярность С. Это язык называют «современным ассемблером». В обычной вычислительной системе переход, например, с 32-разрядного процессора на 64-разрядный по-прежнему будет требовать изменений в программе на С. А это снижает переносимость С-программ.
Для иллюстрации рассмотрим опыт Digital. Последние несколько лет эта фирма продает свои машины с 64-разрядным процессором Alpha. Однако две основные операционные системы, используемые на этих компьютерах – Open VMS самой Digital и Windows NT фирмы Microsoft – все еще 32-разрядные, хотя и написаны, в основном, на С. Приложения для этих операционных систем, также 32-разрядные. Простая перекомпиляция здесь не поможет. Чтобы задействовать все ресурсы процессора, и операционные системы, и приложения надо полностью переписать, и это займет много лет.
HP также загнала покупателей своей HP 9000 в трясину переделок. Сейчас HP продает 64-разрядные версии своих процессоров PA-RISC. Чтобы воспользоваться преимуществами новых аппаратных средств, заказчикам HP придется ждать появления новой 64-разрядной ОС, и затем переписывать свои приложения. На это потребуется столько времени, что уже теперь, задолго до того, как переделка ПО будет завершена (см. главу 12), есть признаки того, что HP может отказаться от дальнейшей разработки HP 9000.
Секрет успешного перехода к 64-разрядным вычислениям на AS/400, в то время как никому больше это не удалось, кроется в ее архитектуре.
Классификация архитектур
Принципов классификации компьютерных архитектур немало. Вероятно, самый старый из них – по формату команд процессора. Другой, уже знакомый, – разделение процессоров на категории CISC и RISC. Оба эти подхода учитывают только аппаратный интерфейс процессора. С точки же зрения заказчика прикладные программы гораздо важнее. Следовательно, не менее законно будет классифицировать компьютерные архитектуры по способу взаимодействия прикладных программ с аппаратным интерфейсом.
Процессоро-ориентированная архитектура
Подавляющее большинство используемых ныне компьютерных архитектур основаны на традиционном подходе, открывающем программисту аппаратный интерфейс. Такие архитектуры называются процессоро-ориентированными (processor-centric) потому, что аппаратный интерфейс в них видим прикладным программам и используется последними непосредственно. Примеры процессоро-ориентированных архитектур – PA фирмы HP и Alpha фирмы Digital.
API-ориентированные архитектуры
Учитывая недостатки процессоро-ориентированных архитектур, многие ISV, производители оборудования и организации по стандартизации совместно разрабатывали архитектуры, в основе которых лежит интерфейс прикладных программ API[ 8 ]8
Аббревиатура API используется (в том числе, и в оригинале книги) в двух значениях: интерфейс прикладных программ в целом и отдельная функция интерфейса прикладных программ. Во втором значении API может употребляться во множественном числе: в английском – APIs, в русском, естественно, без изменения. – Прим. переводчика.
[Закрыть] (application programming interface). Такие API-ориентированные архитектурыустанавливают коммуникационный барьер – интерфейс, который используется всем прикладными программами для доступа к сервисам операционной системы и изолирует их от аппаратных и программных деталей.
Операционная система – это набор программ, управляющих системными ресурсами и служащих фундаментом для написания прикладных программ. Часто таким фундаментом становятся API. Существуют различные формы реализации API. Это может быть вызов или команда, запрашивающая у операционной системы согласие на выполнение некоторых действий. Хорошо известный пример API – функция операционной системы, вызываемая прикладной программой для выполнения операции ввода-вывода, такой как чтение с диска. Очевидно, что прикладной программе незачем «знать» подробности внутренней работы ввода-вывода. Программы операционной системы, выполняющие функции ввода-вывода и часто называемые подсистемами ввода-вывода, изолируют приложения от деталей аппаратной и программной реализации. Приложения, использующие для выполнения ввода-вывода только соответствующие API, не зависят от каких-либо изменений в структуре ввода-вывода на нижних уровнях.
Дополнительное преимущество дает реализация разными производителями одного и того же набора API. В этом случае приложения легко переносить с одной системы на другую. Один из наиболее известных стандартных наборов API – POSIX. POSIX – сокращение, неформально расшифровываемое как «переносимый интерфейс операционной системы базирующейся на Unix» (portable operating system interface based on Unix) – это набор международных стандартов для интерфейсов Unix-подоб-ных операционных систем. Правительственные и неправительственные организации поощряют реализацию производителями Unix-подобных операционных систем данных стандартов, как обеспечивающую переносимость приложений с одной системы на другую.
Общая проблема стандартов типа POSIX состоит в том, что они никогда не становятся законченными, и стадия определения такого стандарта занимает многие годы. В такой ситуации разработчики приложений часто берут дело в свои руки. В 1993 году группа разработчиков приложений для Unix и производителей Unix-подобных операционных систем решила определить свой собственный набор API. Они не могли ждать, пока спецификация POSIX «созреет» до такой степени, чтобы ее можно было использовать. Кроме того, ясно, что когда спецификация POSIX будет, наконец, полностью завершена, все приложения придется переписывать под новый стандарт.
Вместо этого, упомянутая группа разработчиков выделила все API, которые используются в настоящее время наиболее популярными приложениями для Unix. Из тысяч существующих Unix-приложений они взяли 50 самых распространенных и выбрали 1179 функций API в качестве основы нового стандарта, который первоначально был назван SPEC1170. Позднее это название было заменено на «Единая Спецификация UNIX» (Single UNIX Specification), и данный стандарт становится теперь новой промышленной спецификацией Unix. Помимо указанных API в него входит часть интерфейсов POSIX. В состав спецификации продолжают включаться новые API.
Очевидная проблема во всей этой работе по определению API была лаконично сформулирована одним из сотрудников института NIST (National Institute of Standards and Technology Национального института стандартов и технологий США): «Самое милое в стандартах – это большой их выбор». В самом деле, множество противоречащих друг другу и быстро изменяющихся стандартов делает невозможным создание приложения, которое было бы переносимо на все платформы. Далее, в главе 11, мы рассмотрим язык программирования Java и предоставляемые им возможности по созданию переносимых приложений.
Более того, эти стандарты не являются полными, то есть во многих случаях приложениям приходится действовать «в обход» API. В результате приложение становится зависимым от аппаратуры и программного обеспечения нижних уровней: в тот момент, когда приложение обходит API, все проблемы, присущие процессоро-ори-ентированным архитектурам, возникают снова.
Машинная архитектура высокого уровня
Истинная независимость от аппаратуры может быть достигнута, если вместо определения отдельных API для разных специфических приложений (что имеет место в случае такой API-ориентированной архитектуры как Single Unix Specification), будет формально определен общий интерфейс для всех приложений. Более того, если в такой интерфейс заложены возможности расширения, то в любое время для достижения переносимости приложений к нему могут быть добавлены API Single UNIX Specification. Именно такой подход лежит в основе архитектуры AS/400, которая определяет законченный набор API для всех приложений и не позволяет последним обходить API.
Независимый от технологии машинный интерфейс (Technology-Independent Machine Interface), который часто называют просто MI[ 9 ]9
Недавно, название этого интерфейса стали сокращать как TIMI. Мне не слишком нравится имя «Тимми» (да простят меня те, кого зовут Тимоти), так что для обозначения машинного интерфейса AS/400 мы будем использовать старую аббревиатуру «MI».
[Закрыть], представляет собой формальное определение интерфейса для всех приложений и большинства компонентов операционной системы. Аппаратура, а также все программное обеспечение операционной системы, которому должны быть доступны подробности аппаратной реализации, располагаются ниже границы MI.
Чтобы понять, как достигается независимость программного обеспечения от изменений в аппаратуре, обусловленных технологическим прогрессом, необходимо кратко рассмотреть, как работает компилятор. Ранее было сказано, что в традиционной процессоро-ориентированной системе компилятор генерирует двоичный машинный код непосредственно из исходного текста, что иногда требует дополнительного шага ассемблирования. В AS/400 компилятор генерирует из исходного текста код MI, который оформляется в виде так называемого шаблона программы. На втором этапе транслятор AS/400 генерирует двоичный код по содержимому шаблона программы. Фактически, этот транслятор выполняет те же действия, что и заключительный проход современного компилятора. Затем, если явно не запрошено его удаление, шаблон программы сохраняется вместе с двоичным кодом в программном объекте. Такая программа называется отслеживаемой (observable). При переносе программного объекта на новую аппаратную базу, например, на 64-разрядный PowerPC, другой транслятор, созданный для новой аппаратуры, перетранслирует шаблон программы в новый двоичный код. Изменений в исходном коде при этом не требуется – чем и достигается независимость от технологии. Более подробное рассмотрение этого вопроса мы отложим до главы 4.
Значимость такой независимости очевидна для пользователей и ISV. Переход на 64-разрядную технологию RISC дает не только более мощный процессор – операционная система и все приложения сразу же становятся 64-разрядными. Для того чтобы воспользоваться преимуществами 64-разрядного оборудования не нужно ничего переписывать. В один день RISC-системы AS/400 получают 64-разрядную операционную систему и десятки тысяч 64-разрядных приложений.
Архитектура AS/400 заслужила титул «расширенной архитектуры приложений» (Advanced Application Architecture), так как предоставляет возможности, которых многие другие вычислительные системы все еще пытаются достичь с помощью API-ориентированного подхода. AS/400 уже сейчас независима от нижележащей технологии. Хотя независимость от аппаратуры важна, но не менее важна и независимость от деталей операционной системы. В AS/400 достигнуто и это. Термин «расширенная архитектура» подразумевает, что к ней могут быть добавлены вновь определяемые API других операционных систем, что обеспечивает еще большую переносимость приложений.
И это тоже есть!
«Это там есть; все там есть!», – восклицает телевизионная реклама известного соуса для спагетти. Вместо того, чтобы покупать ингредиенты и делать соус самому – убеждает голос за кадром – лучше просто купить бутылку этого соуса и быть уверенным, что все качественные и свежие составляющие, которые Вы использовали бы, уже там. Гленн Ван Беншотен (Glenn Van Benschoten), системный менеджер AS/400, любит использовать аналогию с соусом для спагетти для описания интегрированной сущности AS/400. Все, что Вы можете пожелать для своего компьютера, уже там есть.
AS/400 – это интегрированная система, и эта характеристика отличает ее от большинства других. Для вычислительной системы интеграция означает, что различные части работают вместе как одно целое. Для заказчика это означает, что систему легче устанавливать, сопровождать и использовать, что снижает накладные расходы в бизнесе.
Если бы Вы спросили разработчика из подразделения в Рочестере, в чем причина успеха AS/400, то вероятно получили бы ответ, что здесь знают, как создавать наилучшие коммерческие многопользовательские системы. Если «нажать» посильнее, Ваш собеседник, вероятно, начнет сравнивать конкретные возможности, такие как база данных или структура защиты, с возможностями других систем. На мой взгляд, главное не в этом. Да, у AS/400 мощная база данных и надежная система защиты, но этим обладают и другие системы. Отличительная черта AS/400, которую многие наши разработчики считают само собой разумеющейся, – то, что все компоненты спроектированы, чтобы работать вместе. Система AS/400 – это больше, чем просто сумма составных частей.
Если задать тот же вопрос ISV, то он, вероятно, скажет, что для AS/400 проще, чем для какой-либо другой платформы, разрабатывать и сопровождать приложения. ISV, имеющие свои приложения как для AS/400, так и для других платформ, например Unix, часто указывают на разницу в численности людей, работающих для одной или другой платформы. Обычно, для разработки приложений для AS/400 требуется гораздо меньше людей, и это также – заслуга интеграции. Гарантируя, что новая добавленная функция будет гладко работать со всеми остальными частями системы, мы сокращаем расходы на разработку для AS/400. Все системы, созданные в Рочес-тере до AS/400 включительно, решены интегрировано, и именно в этом секрет их успеха.
Но если даже наши собственные разработчики порой забывают об этом факторе, то благодаря чему AS/400 остается интегрированной системой? Ответ – MI. MI делает для обеспечения интеграции две вещи. Во-первых, он предоставляет общий интерфейс для всех приложений и функций операционной системы, реализованных поверх него, благодаря чему всем приходится использовать систему одинаковым образом. Во-вторых, MI – функционально законченный интерфейс. Так как обойти его невозможно, MI предоставляет все функции, которые могут потребоваться прикладной или системной программе. Если какая-либо нужная функция отсутствует, то программа не будет работать на AS/400. MI также обладает большими возможностями расширения, что позволяет включать в него новые функции по мере надобности.
Прежде чем кто-нибудь укажет на то, что другие системы Рочестера, такие как System/36, добивались интеграции без машинного интерфейса высокого уровня, я должен отметить, что MI обеспечивает и интеграцию, и аппаратную независимость. У System/36 был эквивалент машинного интерфейса для большинства системных функций, но не для приложений. В этой системе два отдельных процессора выполняли: один – пользовательские приложения, а другой – некоторые функции операционной системы. Доступ к этим функциям на втором процессоре был возможен только посредством строго определенного интерфейса между двумя процессорам. Данный интерфейс, подобно MI, гарантировал полноту набора функций и возможность их совместной работы. Приложения, однако, по-прежнему зависели от аппаратуры. По этой причине (как мы увидим в главе 3) для выполнения приложений System/36 на другой аппаратуре требовался эмулятор.
Отрицательная сторона интеграции – отсутствие гибкости. В интегрированных решениях обычно имеет место подход «все или ничего». Клиент не может выбрать
ОС одного производителя, базу данных – другого и пакет защиты – третьего, так как все они не предназначены для работы в интегрированной системе.
Трудно поверить в то, что в любой компьютерной системе есть компоненты, не предназначенные для тесной совместной работы, но часто именно так и обстоит дело. Такие компоненты как базы данных, подсистемы защиты и коммуникаций обычно разрабатываются независимо друг от друга и могут предназначаться для работы с разными ОС. В результате, такие компоненты обычно самодостаточны, то есть стремятся использовать минимальный набор возможностей, встроенных в ОС. Подобное разделение ведет к дублированию функций между ОС и отдельными компонентами. Оно также может привести к разным интерфейсам пользователя и системного оператора.
Преимущество набора из отдельных компонентов состоит в гибкости. Недостаток – в том, что заказчик должен самостоятельно интегрировать такие компоненты в своей вычислительной системе, а это связано с расходами, и не только на собственно интеграцию. Средства тратятся на обучение пользователей и операторов работе с разными интерфейсами, а также на сопровождение. Модернизации одного компонента могут оказать негативное влияние на другой. Все еще более усложняется при использовании компьютеров в сети, которая сама по себе требует сопровождения. В попытке устранить множество несовместимостей между компонентами некоторые предприятия решают закупать все ПО у одного производителя. Но и это обычно не решает проблему.
В общем, ситуация напоминает мне ту, в которой я оказался не так давно при покупке и установке новой аудиовидеосистемы. Каждый из четырех ее компонентов имел собственный пульт дистанционного управления. Поскольку все компоненты произведены одной фирмой, продавец заверил меня, что каждый пульт универсален, то есть может управлять всеми частями комплекса, а следовательно для системы в целом нужен всего один пульт. В действительности оказалось, что с помощью одного пульта можно управлять лишь некоторыми функциями каждого компонента, но не всей системой в целом: для этого надо использовать все четыре пульта. Кроме того, «пользовательские интерфейсы» пультов разные, кнопки для выполнения одной и той же функции находятся на них в разных местах и часто имеют разную форму и размер. Даже названия некоторых идентичных функций различаются. Точно также многим пользователям компьютеров приходится использовать несколько «пультов управления» при эксплуатации своих вычислительных систем. И им, и мне больше подошла бы интегрированная система.