Як працюють номери SO (спільний об’єкт)?


123

Мені відомо, що спільні об'єкти в Linux використовують "так числа", а саме, що різні версії спільного об'єкта отримують різні розширення, наприклад:

  • example.so.1
  • example.so.2

Я розумію, що ідея полягає в тому, щоб мати два різних файли, щоб дві системи бібліотеки могли існувати в системі (на відміну від "DLL Hell" в Windows). Я хотів би знати, як це працює на практиці? Часто я бачу, що example.soнасправді є символічним посиланням на те, example.so.2де .2є остання версія. Як тоді програма залежно від старішої версії example.soідентифікує її правильно? Чи існують правила щодо того, які числа потрібно використовувати? Або це просто умова? Це так, що, на відміну від Windows, де програмні файли передаються між системами, якщо система має більш нову версію спільного об'єкта, вона автоматично підключається до старої версії при компілюванні з джерела?

Я підозрюю, що це пов'язано, ldconfigале я не знаю, як.

Відповіді:


87

Самі бінарні файли знають, від якої версії спільної бібліотеки вони залежать, і запитують її конкретно. Ви можете використовувати lddдля показу залежностей; мої для ls:

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

Як бачите, це вказує на, наприклад libpthread.so.0, не просто libpthread.so.


Причина символічного посилання - у лінкері. Коли ви хочете зв’язатись libpthread.soбезпосередньо, ви даєте gccпрапор -lpthread, і він додає libпрефікс і .soсуфікс автоматично. Ви не можете сказати, щоб він додав .so.0суфікс, тому символічне посилання вказує на найновішу версію lib, щоб зробити це


Знак рівності "= ls" не повинен бути присутнім. Просто використовуйте "ldd ls"
bmacnaughton

1
@bmacnaughton Це, ймовірно, призведе до помилки, оскільки lddвимагає повного шляху до виконуваного файлу. =lsробить це в zsh, але я змінив його, оскільки не всі користуються цією оболонкою
Michael Mrozek

Цікаво. Я запускаю bash на Ubuntu і, здається, працює без повного шляху. Дякую за пояснення - я не використовую zsh.
bmacnaughton

60

Номери в спільних бібліотеках є звичайними умовами, які використовуються в Linux для ідентифікації API бібліотеки. Зазвичай формат такий:

libFOO.so.MAJOR.MINOR

І як ви помітили, зазвичай є символічне посилання від libFOO.so до libFOO.so.MAJOR.MINOR. ldconfig несе відповідальність за оновлення цього посилання до новітньої версії.

ГОЛОВНЕ, як правило, збільшується при зміні API (нові точки введення видаляються або змінюються параметри або типи). MINOR, як правило, збільшується для випусків виправлень помилок або при введенні нових API, не порушуючи існуючі API.

Тут можна ознайомитись з більш широкою дискусією: Розбирання спільних бібліотек


Привіт Мігель, спасибі за це, сором, я не можу прийняти дві відповіді, тому що це прекрасно доповнює сказане. +1 від мене, відмінне посилання теж, ще раз дякую!

4
Це майже правильно, але це насправді libFOO.so.MAJOR.MINOR(так не в кінці)
JonnyJD

6
Ця відповідь така неправильна . По-перше, цифри, які ви бачите, не мають нічого спільного з API, це суто ABI. По-друге, умова тут не є семантичним версією НА ВСІХ, як ви пропонуєте. Швидше це конвенція про libtool, яка має приємне властивість відображення на один номер версії бібліотеки, який ld.so може порівняти ( для отримання додаткової інформації див. Gnu.org/software/libtool/manual/html_node/… )
NewbiZ

23

Спільні бібліотеки повинні бути впорядковані за такою схемою:

blah.so.X.Y.Z

де

  • X = назад несумісний випуск ABI
  • Y = зворотний сумісний випуск ABI
  • Z = лише внутрішні зміни - без змін ABI

Зазвичай ви бачите лише першу цифру, як-от, hello.so.1тому що перша цифра - це єдине, що потрібно для ідентифікації "версії" бібліотеки, оскільки всі інші цифри зворотно сумісні.

ldconfigпідтримує таблицю того, які спільні бібліотеки доступні в системі та де існує шлях до цієї бібліотеки. Ви можете підтвердити це, запустивши:

ldconfig -p

Коли пакет побудований для чогось на зразок Red Hat, спільні бібліотеки, що викликаються у бінарному файлі, будуть шукатись та додані як залежності цього пакету під час збирання RPM. Тому, коли ви переходите до встановлення пакета, інсталятор буде шукати, встановлений чи ні hello.so.1в системі, перевіривши ldconfig.

Ви можете побачити залежності пакету, зробивши щось на зразок:

rpm -qpR hello.rpm

Ця система (на відміну від Windows) дозволяє hello.soвстановити у версії декілька версій системи та одночасно використовувати різні програми.


Я думаю, що це найкраща відповідь.
Kemin Zhou

1
Спільні бібліотеки повинні бути розроблені відповідно до наступної схеми (…) - Чи можете ви надати посилання на це твердження?
Пьотр Доброгост

19

libNAME.so - це ім'я файлу, яке використовує компілятор / посилання під час першого пошуку бібліотеки, визначеної -lNAME. Всередині файлу спільної бібліотеки знаходиться поле під назвою SONAME. Це поле встановлюється, коли сама бібліотека вперше пов'язана в спільний об'єкт (так) процесом збирання. Цей SONAME - це фактично те, що лінкер зберігає у виконуваному файлі залежно від того, що спільний об'єкт пов'язаний з ним. Зазвичай SONAME є у формі libNAME.so.MAJOR і змінюється в будь-який час, коли бібліотека стає несумісною з існуючими виконуваними файлами, пов'язаними з нею, і обидві основні версії бібліотеки можуть бути встановлені в міру необхідності (хоча для розробки вказуватиметься лише одна як libNAME.so) Крім того, для підтримки легкого оновлення між незначними версіями бібліотеки, libNAME.so.MAJOR, як правило, є посиланням на такий файл, як libNAME.so.MAJOR.MINOR. Можна встановити нову незначну версію і після її завершення посилання на стару другорядну версію зіткнеться, щоб вказувати на нову другорядну версію негайно оновлення всіх нових виконань для використання оновленої бібліотеки. Також дивіться мою відповідь наLinux, GNU GCC, ld, сценарії версій та двійковий формат ELF - Як це працює?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.