За счет каких действий достигается двоичная совместимость для процессоров различных архитектур
Создание полноценной прикладной среды, полностью совместимой со средой другой операционной системы, является достаточно сложной задачей, тесно связанной со структурой операционной системы. Существуют различные варианты построения множественных прикладных сред, отличающиеся как особенностями архитектурных решений, так и функциональными возможностями, обеспечивающими различную степень переносимости приложений.
Во многих версиях ОС UNIX транслятор прикладных сред реализуется в виде обычного приложения. В операционных системах, построенных с использованием микроядерной концепции, таких, как, например, Windows NT, прикладные среды выполняются в виде серверов пользовательского режима. А в OS/2 с ее более простой архитектурой средства организации прикладных сред встроены глубоко в операционную систему.
Один из наиболее очевидных вариантов реализации множественных прикладных сред основывается на стандартной многоуровневой структуре ОС. На рис. 2. 7 операционная система OS1 поддерживает кроме своих «родных» приложений приложения операционной системы OS2. Для этого в ее составе имеется специальное приложение – прикладная программная среда, которая транслирует интерфейс «чужой» операционной системы –API OS2 в интерфейс своей «родной» операционной системы –
API OS1.
Приложение OS2 |
API OS2 |
Транслятор системных вызовов |
API OS1 |
Менеджеры ресурсов |
Базовые механизмы |
Машинно-независимые модули |
Рис. 2. 7. Прикладная программная среда, транслирующая
системные вызовы
В другом варианте реализации множественных прикладных сред операционная система имеет несколько равноправных прикладных програм-мных интерфейсов. В приведенном на рис. 2. 8 примере операционная си-стема поддерживает приложения, написанные для OS1, OS2 и OS3. Для этого непосредственно в пространстве ядра системы размещены прикладные программные интерфейсы всех этих ОС: API OS1, API OS2 и API OS3.
API OS1 | API OS2 | API OS3 |
Менеджеры ресурсов | ||
Базовые механизмы | ||
Машинно-независимые модули |
Рис. 2. 8. Реализация совместимости на основе нескольких
равноправных API
В этом варианте функции уровня API обращаются к функциям нижележащего уровня ОС, которые должны поддерживать все три в общем случае несовместимые прикладные среды. В разных ОС по-разному осуществляется управление системным временем, используется разный формат времени дня, на основании собственных алгоритмов разделяется процессорное время и т. д. Функции каждого API реализуются ядром с учетом специфики соответствующей ОС, даже если они имеют аналогичное назначение.
Еще один способ построения множественных прикладных сред основан на микроядерном подходе. При этом очень важно отделить базовые, общие для всех прикладных сред, механизмы операционной системы от специфических для каждой из прикладных сред высокоуровневых функций, решающих стратегические задачи.
В соответствии с микроядерной архитектурой все функции ОС реализуются микроядром и серверами пользовательского режима. Важно, что каждая прикладная среда оформляется в виде отдельного сервера пользовательского режима и не включает базовых механизмов (рис. 2. 9). Приложения, используя API, обращаются с системными вызовами к соответствующей прикладной среде через микроядро. Прикладная среда обрабатывает запрос, выполняет его (возможно, обращаясь для этого за помощью к базовым функциям микроядра) и отсылает приложению результат. В ходе выполнения запроса прикладной среде приходится, в свою очередь, обращаться к базовым механизмам ОС, реализуемым микроядром и другими серверами ОС.
Приложения Серверы ОС
Рис. 2. 9. Микроядерный подход к реализации множественных
прикладных сред
Такому подходу к конструированию множественных прикладных сред присущи все достоинства и недостатки микроядерной архитектуры, в частности:
очень просто можно добавлять и исключать прикладные среды, что является следствием хорошей расширяемости микроядерных ОС;
надежность и стабильность выражаются в том, что при отказе одной из прикладных сред все остальные сохраняют работоспособность;
низкая производительность микроядерных ОС сказывается на скорости работы прикладных сред, а значит, и на скорости выполнения приложений.
Создание в рамках одной операционной системы нескольких прикладных сред для выполнения приложений различных ОС представляет собой путь, который позволяет иметь единственную версию программы и переносить ее между операционными системами. Множественные прикладные среды обеспечивают совместимость на двоичном уровне данной ОС с приложениями, написанными для других ОС. В результате пользователи получают большую свободу выбора операционных систем и более легкий доступ к качественному программному обеспечению.
Вопросы для самопроверки
49. В чем отличие микроядерной архитектуры от традиционной архитектуры ОС?
50. Почему микроядро хорошо подходит для поддержки распределенных вычислений?
51. Что подразумевается под концепцией множественных прикладных сред?
52. В чем суть метода трансляции библиотек?
Контрольные вопросы
53. Каким термином в микроядерной архитектуре принято называть менеджеры ресурсов, вынесенные в пользовательский режим?
54. Можно ли считать микроядерную архитектуру в высокой степени переносимой?
55. Почему микроядерная архитектура ОС в большей степени расширяемая, чем классическая ОС?
56. Является ли микроядерная архитектура более надежной, чем традиционная?
57. Укажите причину, из-за которой производительность микроядерной архитектуры хуже традиционной схемы ОС.
58. Можно ли считать ОС Windows NT 4.0 системой с микроядерной архитектурой?
59. Какие виды совместимости Вам известны?
60. За счет каких действий достигается двоичная совместимость для процессоров различных архитектур?
61. Укажите способ, который позволяет повысить производительность ПК при выполнении «чужого» исполняемого файла.
62. Достаточно ли одного метода трансляции библиотек для полной совместимости приложений?
Возможно, многие из вас задавались вопросами вроде «А что будет, если кто-то подложит к моему приложению неправильную версию библиотеки?». Вопрос хороший, а ответ на него и некоторые другие вы найдёте в этом топике. Для затравки задачка: пусть есть два интерфейса и класс, реализующий один из них:
А также класс, в котором есть метод foo , перегруженный для A и B . Этот метод вызывают от экземпляра класса C :
Вполне очевидно, что выведется «A». Не менее очевидно, что если сказать, что C implements A, B , то получится ошибка компиляции ( тем, кому последнее не очевидно, могу порекомендовать почитать про то, как происходит выбор методов. Например, в стандарте в разделе 15.12.2 или в более просто описывающих местах ).
Но вот что произойдёт, если мы перекомпилируем только C.java , а потом запустим CompatibilityChecker из уже имеющегося класс-файла, является уже более сложным вопросом. Заинтересованы? Прошу под кат!
Те, кто знают, что перегруженные методы выбираются во время компиляции, могут сообразить, что по этой причине в класс-файле будет сразу записана информация о том, какой же метод вызывать, и потому в результате выведется «A». Проверим это предположение:
Действительно, как можно заметить по инструкции с отступом 19, идёт вызов вполне конкретного метода. Впрочем, те, кто слышал про верификатор, могут возразить и предположить, что он заметит, что это какие-то не те пчёлы класс C изменился, и швырнёт исключение. К счастью, они ошибаются, ведь верификатор проверяет только лишь корректность структуры классов и интерфейсов, а не соответствие версий класс-файлов.
Итак, запустим-таки наш код и убедимся, что изначальное предположение было правильным: выведется действительно «А».
Кроме того, можно предположить, что в виртуальной таблице адресов может оказаться какой-то неправильный адрес, и потому всё сломается в рантайме с NoSuchMethodError . Это предположение тоже ошибочно, так как вызывается метод foo(A) , и в виртуальной таблице он такой один. Другое дело, если бы были наследники, его переопределяющие…
Пусть у нас есть три следующих класса:
И класс, вызывающий foo в разных вариантах:
Все, конечно же, знают, что поскольку у переотпределённых типов методы выбираются в рантайме, изначальный вывод будет таким:
Самое время сделать пакость, подменив класс-файл от A на результат компиляции следующего кода:
Понять, что в данном случае произойдёт, довольно просто. Во-первых, все попытки вызвать методы, где foo вызывается у экземпляпа класса A , точно вылетят с NoSuchMethodError . Среди этих попыток также находится и вызов super.foo() в классе C . Во-вторых, как мы уже видели раньше, метод B.foo() вызовется успешно.
Теперь изменим тактику: снова сделаем A.foo таким, каким он и был, но теперь поменяем B и C , вообще удалив из них переопределение метода foo :
При запуске кода dynamic dispatch обнаружит только по одной записи для A.foo , и потому во всех случаех вызовет его, в результате чего мы увидем в консоли только буквы «A» и полное отсутствие каких-либо исключений.
Продолжим наши изыскания, снова переопределив методы в B и C . После запуска, как мы и можем ожидать, dynamic dispatch обнаружит все записи в виртуальной таблице, и даст точно такой же вывод, как и тот, который мы получили бы, заново перекомпилировав всё.
Ранее мы пробовали экспериментировать только с методами. Посмотрим теперь, что бывает с полями. Пусть есть класс, хранящий значение типа int и наследник этого класса:
И, традиционно, потребитель класса B :
Добавим теперь в класс B собственное поле с таким же именем:
Посмотрим, какой байт-код был сгенерирован для CompatibilityChecker :
Этот листинг может сбить с толку, полкольку на отступе 11 в комменте вроде как сказано, что поле принадлежит B. Потому стоит полагать, что при перекомпиляции B мы столкнёмся с ошибкой. Однако оказывается, что это вовсе не так. Поскольку физически поле есть только у базового класса, операнд команды putfield указывает именно на то самое нужное поле, в результате чего после изменений код продолжает работать.
- Изменение реализации существующих методов, конструкторов или блоков инициализации
- Добавление новых полей, методов и конструкторов существующим классам и интерфейсам
- Удаление приватных полей, методов и конструкторов класса
- Перемещение методов наверх по иерархии классов
- Добавление новых классов и интерфейсов
Как выяснилось, спецификация недостаточно строга, и можно придумать случай, в котором безопасные изменения приведут к ошибке в линковке. Рассмотрим интерфейс, класс, реализующий этот интерфейс, и ещё один класс, использующий их:
Произведём два безопасных изменения: добавим метод foo в интерфейс A и изменим реализацию метода main класса CompatibilityChecker :
При запуске, как вы могли понять, произойдёт ошика, а именно AbstractMethodError: B.foo()V , чего по идее быть не должно. Эту проблема известна и лежит в самой основе обработки байт-кода Java. Были предложения по исправлению ситуации, но они пока ни к чему не привели.
Конец
Итак, ответ на вопрос, профигурировавший в самом начале статьи («А что будет, если кто-то подложит к моему приложению неправильную версию библиотеки?») такой: «А кто ж его знает. Смотря в чём та версия, которая использовалась при компиляции, отличается от той, которая используется в рантайме».
В статье не затронуты некоторые очевидные вещи. Например, что при несовместимых изменениях вроде удаления методов и классов или превращения класса в интерфейс, будут кидаться беспощадные ошибки вроде NoSuchMethodError , NoClassDefFoundError или IncompatibleClassChangeError .
Буду рад ответить на вопросы и прочитать замечания и дополнения. Кстати, это мой первый топик во второй жизни на Хабрахабре. Даже не знаю, к чему это говорю.
Двои́чная совмести́мость, бина́рная совмести́мость (англ. binary compatibility ) — вид совместимости программ, позволяющий программе работать в различных средах без изменения её исполняемых файлов.
Этот термин часто используется в значении «совместимость операционных систем», и в таком случае означает способность уже скомпилированной версии программы для одной операционной системы работать в другой операционной системе без перекомпиляции. К примеру, практически все программы, написанные для Windows 2000, можно запустить в Windows XP — это означает, что Windows 2000 и Windows XP бинарно совместимы.
Двоичная совместимость включает в себя побайтовую совместимость полей загрузки, полную идентичность механизма вызова функций, передачи переменных и получения результата вычислений, и полную реализацию интерфейса программирования. При этом технически реализация может быть совершенно иной, — главное, чтобы были реализованы все вызовы и чтобы они приводили к ожидаемому результату, а каким способом этот результат достигается, решают создатели программы.
Слом двоичной совместимости означает прекращение поддержки программ и обязательное требование перекомпиляции и возможных исправлений в программе, чтобы она заработала. К примеру, после того, как компания Apple начала использовать в своих компьютерах процессоры Intel, была сломана двоичная совместимость со всеми приложениями, написанными для процессоров PowerPC. Чтобы не лишиться всех разработанных в прошлом программых продуктов для операционной системы Mac OS, компания Apple использует лёгкий транслятор Rosetta, переводящий вызовы операционной системы Mac OS для PowerPC в вызовы Mac OS для Intel. Этот пример демонстрирует также возможный метод борьбы со сломом двоичной совместимости.
В операционной системе Solaris 10 для x86 существует возможность запускать приложения для Линукса без перекомпиляции с помощью BrandZ. На платформе SPARC такая возможность отсутствует.
См. также
Смотреть что такое "Двоичный интерфейс приложений" в других словарях:
Интерфейс программирования приложений — (иногда интерфейс прикладного программирования) (англ. application programming interface, API [эй пи ай])[1] набор готовых классов, процедур, функций, структур и констант, предоставляемых приложением (библиотекой, сервисом) для… … Википедия
Двоичный формат файлов Microsoft Excel 97—2007 — Microsoft Excel (Windows) Microsoft Excel 2007 Тип Табличный процессор Разработчик ОС Microsoft Windows … Википедия
Двоичный формат файлов Microsoft Excel 97—2000 — Microsoft Excel (Windows) Microsoft Excel 2007 Тип Табличный процессор Разработчик ОС Microsoft Windows … Википедия
Двоичный формат файлов Microsoft PowerPoint 97—2007 — Microsoft PowerPoint Скриншот Microsoft PowerPoint 2007 Тип программа для создания презентаций Разработчик Майкрософт … Википедия
Двоичный формат файлов Microsoft PowerPoint 97—2000 — Microsoft PowerPoint Скриншот Microsoft PowerPoint 2007 Тип программа для создания презентаций Разработчик Майкрософт … Википедия
RISC OS — У этого термина существуют и другие значения, см. RISC (значения). RISC OS Скриншот RISC OS 4 Разработчик … Википедия
Двоичная совместимость — Двоичная совместимость, бинарная совместимость (англ. binary compatibility) вид совместимости программ, позволяющий программе работать в различных средах без изменения её исполняемых файлов. Этот термин часто используется в значении… … Википедия
Бинарная совместимость — Двоичная совместимость, также бинарная совместимость от англ. binary compatibility вид совместимости программ, позволяющий программе работать в различных средах без изменения её двоичных файлов. Этот термин часто используется в значении… … Википедия
Модель OSI — Сетевая модель OSI (базовая эталонная модель взаимодействия открытых систем, англ. Open Systems Interconnection Basic Reference Model) абстрактная сетевая модель для коммуникаций и разработки сетевых протоколов. Представляет уровневый подход к… … Википедия
См. также
Это заготовка статьи о компьютерах. Вы можете помочь проекту, исправив и дополнив её. Это примечание по возможности следует заменить более точным. |