что такое * .so. *. * libs - PullRequest
       32

что такое * .so. *. * libs

4 голосов
/ 15 сентября 2010

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

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

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

Ответы [ 2 ]

8 голосов
/ 15 сентября 2010

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


Фактические детали реализации могут несколько отличаться (я основываю свой ответ на более ранних версиях UNIX, и 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, получат определенную младшую версию определенной основной версии.
6 голосов
/ 15 сентября 2010

Это схема управления версиями для разделяемых библиотек .Каждая библиотека должна иметь 3 имени:

  1. Реальное имя: фактическое имя библиотеки, libfoo.so.1.2.3
  2. "SONAME": theимя записывается в исполняемый файл и ищет динамический компоновщик имени, 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 во время выполнения из-за SONAME.Затем вы обновляетесь до исправленного, но совместимого с двоичным кодом 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 и не нуждается в обновлении.

...