Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Программирование и алгоритмические языки


Ulrich Drepper "Как писать разделяемые библиотеки"
Назад Оглавление Вперед

3.3. Контроль версий ABI

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

Первый способ является самым старым и достаточно грубым. Это реализуется при помощи использования различных имен файла для каждой несовместимого объекта DSO. В двоичных файлах ELF зависимости от объектов DSO задаются с помощью указания записей DT NEEDED в динамическом сегменте. Строка, ассоциированная с записью, должен быть именем существующего объекта DSO. Оно обычно берется из строки, ассоциированной с записью DT SONAME в объекте DSO. Разные имена могут указывать на различные файлы, что делает сосуществование различных DSO возможным и простым. Но хотя этот метод использовать просто и можно легко создавать такие объекты DSO, у него есть серьезный недостаток. Для каждой реализованной версии DSO, в которой есть несовместимые изменения, нужно изменять SONAME. Это может привести к большому числу версий DSO, каждая из которых лишь слегка отличается друг от друга. Из-за этого в случае, когда для запуска приложения нужно более одной версии DSO, ресурсы времени выполнения становятся более громозкими. Еще одной проблемой является ситуация, когда одно приложение загружает более одной версии DSO. Это возможно в случае, если зависимости (другие DSO, которые нужны приложению) самостоятельно загружают эти различные версии. Поскольку в двух версиях DSO нечего не известно друг о друге, то результаты могут быть катастрофическими. Единственный безопасный способ справиться с именами файлов различных версий, это полностью избегать описанной ситуации. Это, скорее всего, возможно только при одновременном обновлении сразу всех двоичных модулей, что означает, что способ эффективного контроля версий отсутствует. Основным преимуществом указания версий в именах файлов является то, что это работает везде и может использоваться в качестве запасного решения в случае, если другие варианты контроля версий нелоступны.

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

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

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

Следует отметить, что число версий значительно меньше, чем количество символов и обычно не зависит от их числа. Новые версии добавляются только в случаях, когда обновляется пакет DSO или версия ОС. Поэтому сравнение версий выполняется быстро.

Хотя расширения Sun помогают справиться с отдельными частями проблемы стабильности, требуется решить гораздо более серьезную проблему: как справиться с несовместимыми изменениями. Рано или поздно в каждом нетривиальном DSO в процессе его существования необходимо делать некоторые несовместимые изменения. В эту категорию иногда попадают даже те изменения, которые делаются для исправления программ. Некоторая (не работающая) программа может зависеть от старого метода. Пока есть только один выход: изменить SONAME.

При использовании механизма контроля версий, имеющегося в Linux, в этом необходимости нет. Интерфейсы ABI обычно могут оставться стабильными настолько долго, сколько потребуется. Механизм контроля версий символов [4] является расширением внутреннего механизма версий, предложенного фирмой Sun. Основных отличия два: для заданного символа можно иметь более одного определения (ассоциированная версия должна отличаться) и в приложении или в объекте DSO, скомпонованными с DSO с контролем версий, имеется не только список необходимых версий, но также для каждого символа специальная запись, в которой указывается, какая версия символа используется и из какого объекта DSO берется определение. Затем, на этапе выполнения приложения, эта информация может использоваться для выбора правильной версии из всех различных версий одного и того же интерфейса. Единственным требованием является согласованность интерфейса API (заголовки, объекты DSO, используемые для компоновки, и документация). В каждом DSO с контролем версий для каждого интерфейса API есть, по меньшей мере, одна версия, которую можно использовать на этапе компоновки. Интерфейс API (но не ABI) может также полностью исчезнуть: это способ прекращения использования устаревшего интерфейса API, что не должно влиять на совместимость на уровне двоичного кода.

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

Если возможно, то в проектах, в которых обычно используются объекты DSO, следует с самого первого дня использовать механизм контроля версий символов. Это выглядит привлекательным, поскольку те же самые методы используются для контроля за экспортом символов. К сожалению, такая схема контроля версий требует изменений в динамическом компоновщике, что в настоящее время есть только в Linux и в GNU Hurd {Примечание 12}. Если это невозможно, то для совместимых изменений используйте внутренний контроль версий, предложенный Sun (на самом деле, это применимо только в Solaris). В противном случае нет никаких вариантов, кроме как изменять SONAME для каждого релиза с несовместимыми изменениями и, возможно, даже для релизов с совместимыми изменениями. Но факт того, что такие ограниченные системы существуют, ни в коем случае не должен рассматриваться как способ реализации: если есть более эффективные механизмы, то они должны использоваться.

Примечание 12: Несомненно, в некоторых вариантах BSD "заимствуются" механизмы контроля версий. Хотя мне об этом никто не говорил.

Предыдущий раздел:   Следующий раздел:
Назад Оглавление Вперед