Вопрос

Когда я делаю ls -l в /usr/lib Я вижу много либеров с "sameName.so.*.*" расширение.

  1. Каково значение этих расширений?
  2. Почему созданы мягкие ссылки? Что они используют?

Один пример очень поможет в понимании.

Это было полезно?

Решение

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

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

Недостаток точно такой же, как и преимущество. Ваш исполняемый файл может обнаружить, что предположения, которые он сделал о базовых библиотеках, были изменены, и это, вероятно, вызовет всевозможные проблемы.

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

Например, допустим, у вас есть версия 1 xyz.so. Анкет У вас есть файл и символическая ссылка на этот файл:

pax> ls -al xyz*
-rw-r--r--  1 pax paxgroup    12345 Nov 18  2009 xyz.so.1
lrwxrwxrwx  1 pax paxgroup        0 Nov 18  2009 xyz.so -> xyz.so.1

Теперь, когда вы создаете исполняемый файл exe1, связывая это с xyz.so, он будет следить за символической ссылкой, чтобы хранить xyz.so.1 в исполняемом файле как то, что нужно загружать во время выполнения.

Таким образом, когда вы обновляете общую библиотеку таким образом:

pax> ls -al xyz*
-rw-r--r--  1 pax paxgroup    12345 Nov 18  2009 xyz.so.1
-rw-r--r--  1 pax paxgroup    67890 Nov 18  2009 xyz.so.2
lrwxrwxrwx  1 pax paxgroup        0 Nov 18  2009 xyz.so -> xyz.so.2

Ваш первоначальный исполняемый файл exe1 будем Все еще Загрузить версию 1 общего объекта.

Однако любые исполняемые файлы, которые вы создаете сейчас (например, exe2) будет связан с версией 2 общего объекта.


Фактические детали реализации могут несколько варьироваться (я основываю свой ответ на более ранних Unixes, и Linux, кажется, делает версию немного более интеллектуально, чем просто следуя символическим ссылкам). У IBM DeveloperWorks есть хорошая статья о том, как это сделано здесь.

Когда вы создаете общий объект, вы даете ему как настоящее имя, так и настоящее имя soname. Анкет Они используются для установки общего объекта (который создает как объект, так и ссылку на него).

Таким образом, вы можете получить ситуацию:

pax> ls -al xyz*
-rw-r--r--  1 pax paxgroup    12345 Nov 18  2009 xyz.so.1.5
lrwxrwxrwx  1 pax paxgroup        0 Nov 18  2009 xyz.so.1 -> xyz.so.1.5
lrwxrwxrwx  1 pax paxgroup        0 Nov 18  2009 xyz.so -> xyz.so.1

с xyz.so.1.5 обладая SONAME из xyz.so.1.

Когда линкер ссылается в xyz.so, он следует по ссылкам вплоть до xyz.so.1.5 и использует свой SONAME из xyz.so.1 хранить в исполняемом файле. Затем, когда ты бежать исполняемый файл пытается загрузить xyz.so.1 что укажет на конкретный xyz.so.1.N (не обязательно версия 1.5).

Так что вы можете установить xyz.so.1.6 и обновить xyz.so.1 Ссылка на то, чтобы указать на него вместо этого, и уже будут выполнены исполняемые файлы вместо этого.

Одним из преимуществ этого многослойного метода является то, что вы можете иметь несколько потенциально несовместимые библиотеки с одинаковыми названиями (xyz.so.1.*, xyz.so.2.*) Но в каждой крупной версии вы можете свободно обновить их так как они должны быть совместимыми.

Когда вы ссылаетесь на новые исполняемые файлы:

  • Те, кто связывается с xyz.so Получит последнюю незначительную версию последней крупной версии.
  • Другие, связывающие с xyz.so.1 Получит последнюю незначительную версию конкретной крупной версии.
  • Третьи, связывающие с xyz.so.1.2 Получит конкретную небольшую версию конкретной крупной версии.

Другие советы

Это Схема управления версиями для общих библиотек. Анкет У каждой библиотеки должно быть 3 имена:

  1. Настоящее имя: Фактическое название библиотеки, libfoo.so.1.2.3
  2. "Soname": Имя записано в исполняемом файле, и ищет динамический линкер, ищет, libfoo.so.1.2. Анкет Это имя фактически написано внутри самого библиотеки и будет записано в исполняемом файле во время ссылки. Обычно это символизирует настоящее имя библиотеки (обычно последняя версия).
  3. Имя линкера: Имя, которое вы даете линкеру при создании своей программы. Обычно ссылки на последнее Soname.

Пример

Скажи, что у тебя есть libfoo Версия 1 установлена: libfoo.so -> libfoo.so.1.0 -> libfoo.so.1.0.0. Анкет Вы строите свою программу bar с -lfoo. Анкет теперь ссылается на libfoo и загрузит libfoo.so.1.0 во время выполнения из -за Сонаме. Затем вы обновляетесь до исправленного, но совместимых с бинарной libfoo.so.1.0.1 заменив настоящий бинарный. bar все еще ссылки на libfoo.so.1.0 и не нужно перестраивать.

Теперь представьте, что вы хотите построить новую программу baz Это использует несовместимые изменения в Libfoo v1.1. Вы устанавливаете новую версию, а в вашей системе установлено две версии, установленные параллельно:

  1. libfoo.so.1.0 -> libfoo.so.1.0.1
  2. libfoo.so -> libfoo.so.1.1 -> libfoo.so.1.1.0

ПРИМЕЧАНИЕ Имя линкера было обновлено до последней версии (это версия, соответствующая заголовкам, которые вы установили в /usr/include).

Вы строите baz, и это связано с libfoo.so и нагрузки libfoo.so.1.1 во время выполнения. Не это bar все еще бежит против libfoo.so.1.0 и не нужно обновляться.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top