как работают числа so (общий объект))?

<p>мне известно, что общие объекты в linux используют "так числа", а именно, что разные версии общего объекта имеют разные расширения, например:</p><ul> <li><code>example.so.1</code></li> <li><code>example.so.2</code></li> </ul><p>я понимаю, что идея состоит в том, чтобы иметь два разных файла, чтобы в системе могли существовать две версии библиотеки (в отличие от "dll hell" в windows). я хотел бы знать, как это работает на практике? часто я вижу, что <code>example.so</code> на самом деле является символической ссылкой на <code>example.so.2</code> где <code>.2</code> это последняя версия. как тогда работает приложение в зависимости от более старой версии <code>example.so</code> определить это правильно? есть ли какие-либо правила относительно того, какие числа нужно использовать? или это просто соглашение? является ли это случаем, что, в отличие от windows, где двоичные файлы программного обеспечения передаются между системами, если в системе имеется более новая версия общего объекта, она автоматически связывается со старой версией при компиляции из исходного кода?</p><p>я подозреваю, что это связано с <code>ldconfig</code>, но я не знаю как.</p>

<p>сами двоичные файлы знают, от какой версии разделяемой библиотеки они зависят, и запрашивают ее специально. вы можете использовать <code>ldd</code>, чтобы показать зависимости; мои для <code>ls</code> являются:</p><pre><code>$ 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) </code></pre><p>как вы можете видеть, это указывает, например, на <code>libpthread.so.0</code>, не просто <code>libpthread.so</code>.</p><hr><p>причиной символической ссылки является компоновщик. когда вы хотите связать с <code>libpthread.so</code> прямо, вы даете <code>gcc</code> флаг <code>-lpthread</code> и добавляет префикс <code>lib</code> и <code>.so</code> суффикс автоматически. вы не можете сказать это, чтобы добавить на <code>.so.0</code> суффикс, поэтому символическая ссылка указывает на новейшую версию библиотеки, чтобы облегчить</p>

<p>числа в общих библиотеках являются условным обозначением, используемым в linux для идентификации api библиотеки. обычно формат таков:</p><pre><code>libfoo.so.major.minor </code></pre><p>и, как вы заметили, обычно есть символическая ссылка от libfoo.so к libfoo.so.major.minor. ldconfig отвечает за обновление этой ссылки до последней версии.</p><p>значение major обычно увеличивается при изменении api (удаляются новые точки входа или изменяются параметры или типы). minor обычно увеличивается для выпусков исправлений ошибок или когда новые api вводятся без нарушения существующих api.</p><p>более подробное обсуждение можно найти здесь: <a href="http://www.ibm.com/developerworks/linux/library/l-shlibs/index.html">разделение разделяемых библиотек</a> </p>

<p>разделяемые библиотеки должны иметь версии по следующей схеме:</p><pre><code>blah.so.x.y.z </code></pre><p>где</p><ul> <li>x = обратно несовместимый выпуск abi</li> <li>y = обратно совместимый выпуск abi</li> <li>z = только внутренние изменения - без изменений в abi</li> </ul><p>обычно вы видите только первую цифру, например <code>hello.so.1</code> потому что первая цифра - единственное, что необходимо для идентификации "версии" библиотеки, поскольку все остальные цифры обратно совместимы.</p><p><code>ldconfig</code> содержит таблицу того, какие общие библиотеки доступны в системе и где существует путь к этой библиотеке. вы можете проверить это, запустив:</p><pre><code>ldconfig -p </code></pre><p>когда пакет создается для чего-то вроде red hat, совместно используемые библиотеки, вызываемые в двоичном файле, будут просматриваться и добавляться как зависимости пакета во время сборки rpm. поэтому при переходе к установке пакета установщик проверяет, является ли <code>hello.so.1</code> устанавливается в систему путем проверки <code>ldconfig</code>.</p><p>вы можете увидеть зависимости пакета, выполнив что-то вроде:</p><pre><code>rpm -qpr hello.rpm </code></pre><p>эта система (в отличие от windows) допускает несколько версий <code>hello.so</code> для установки в системе и одновременного использования различными приложениями.</p>

<p>libname.so - это имя файла, используемое компилятором/компоновщиком при первом поиске библиотеки, указанной в -lname. внутри файла общей библиотеки находится поле под названием soname. это поле устанавливается, когда сама библиотека сначала связывается в общий объект (то есть) в процессе сборки. этот soname - это то, что компоновщик хранит в исполняемом файле, в зависимости от того, с каким общим объектом он связан. обычно soname имеет вид libname.so.major и изменяется каждый раз, когда библиотека становится несовместимой с существующими исполняемыми файлами, связанными с ней, и обе основные версии библиотеки могут быть установлены по мере необходимости (хотя для разработки будет указана только одна). as libname.so) кроме того, для поддержки простого обновления между второстепенными версиями библиотеки libname.so.major обычно представляет собой ссылку на файл, подобный libname.so.major.minor. можно установить новую минорную версию, и после ее завершения ссылка на старую минорную версию будет увеличена, чтобы указать на новую минорную версию, немедленно обновляющую все новые исполнения для использования обновленной библиотеки. также см. мой ответ на <a href="https://unix.stackexchange.com/questions/5719/linux-gnu-gcc-ld-version-scripts-and-the-elf-binary-format-how-does-it-work/10317#10317">linux, gnu gcc, ld, сценарии версий и двоичный формат elf - как это работает?</a> </p>