Как устроены версии shared libraries в Linux
Абракадабра! Сегодня обсудим «сосо́чки» и их версионность.
читать первым в телеграм читать первым в макс
Как ты знаешь, в Linux есть файлы с расширением .so. Это и есть «сосо́чки». А ты думал?
Если такие файлы бездумно удалять или подменять из других дистрибутивов, велика вероятность, что всё встанет раком.
У меня была история в начале карьеры, когда я бездумно удалил файлы на сервере, и корпоративная 1С приказала долго жить. Удалил по причине — чистил место. Бэкапов, естественно, я не сделал.
Лошара чо, так я получил новое достижение — седой волос на жопе.
Сосо́чки — это разделяемые библиотеки, то бишь shared libraries. Короче, если ты немного программист, то знаешь, что эти библиотеки содержат набор неких функций.
Допустим, написал ты свой бинарник, а все функции для бинарника вынес в отдельный файл bashdays.so. Теперь бинарник будет ходить в этот «сосочек» и читать оттуда нужные ему функции.
Ранее я писал пост, как создавать свои «сосо́чки» и обращаться к ним из Bash-скриптов.
А зачем так усложнять? Всё просто, ты выносишь протестированные функции в отдельный файл. А потом можешь их использовать совершенно из другого бинарника.
Грубо говоря, у тебя есть 10 софтин и один «сосо́чек». Все эти 10 софтин ходят в сосочек и забирают нужное. Оптимизация? Ещё какая!
Ну так вот. К «сосо́чкам» применяется версионность. То есть у тебя может быть несколько таких библиотек с разными функциями:
libbashdays.so.1.0.0
libbashdays.so.1.1.0
libbashdays.so.1.1.1
Версионность нужна для совместимости. Она позволяет сохранить работоспособность программ при обновлениях.
Ну ты понял. Условный apache использует libbashdays.so.1.0.0, а условный nginx, который был обновлён, уже хочет версию 1.1.1. Чтобы не сломать apache, нужно иметь 2 версии «сосо́чка».
Разделяемая библиотека должна состоять из трёх имён:
- имя библиотеки;
- метка soname;
- компоновочное имя.
Имя библиотеки — в формате lib<name>.so.<major>.<minor>.<patch>.
- Major — правки приводят к несовместимости;
- Minor — добавление функционала;
- Patch — багфиксы, оптимизации.
Метка Shared Object Name, или soname, представляет идентификатор, который позволяет системе динамической загрузки (dynamic linker) определить, какая версия библиотеки должна быть загружена для выполнения программ.
Если софтина скомпилирована с использованием libbashdays.so.1.0.0, она будет искать libbashdays.so с soname 1 при запуске.
Это значит, что она может работать как с libbashdays.so.1.0.0, так и с libbashdays.so.1.1.0, поскольку у них одинаковый soname. Однако она не будет работать с libbashdays.so.2.0.0, так как у этой версии другой soname.
Создаём libbashdays.so.1.0.0 с меткой libbashdays.so.1:
gcc -shared -Wl,-soname=libbashdays.so.1 -o libbashdays.so.1.0.0 module.o
Компоновочное имя связывает приложение и библиотеку.
gcc -g -Wall -o bashdays main.o libbashdays.so
В исполняемый файл bashdays будет записан soname с привязкой к libbashdays.so.
Чтобы корректно подключать зависимости, создаётся пара символических ссылок.
libbashdays.so -> libbashdays.so.1
libbashdays.so.1 -> libbashdays.1.0.0
libbashdays.1.0.0
Старайся, чтобы компоновочное имя ссылалось на метку soname. На случай, если пользователь-дебил удалит старую версию минорного обновления и симлинка поломается.
Так. После всех этих танцев с бубном ссылка на soname должна указывать на самую последнюю её версию. Тогда приложение будет работать с самой актуальной версией библиотеки.
libbashdays.so.1 -> libbashdays.so.1.0.1
Ну и при обновлениях мажорных версий, используя утилиту ldconfig, автоматически будет создана ссылка, которая свяжет имя библиотеки и метку soname. Приложение будет работать с последней совместимой версией.
ldconfig -v | grep libbashdays
libbashdays.so.2 -> libbashdays.so.2.0.0 (changed)
$ ldd bashdays
libbashdays.so.1 => ./libbashdays.so.1 (0x0000ffff6f680000)
libc.so.6 => /lib/libc.so.6 (0x0000ffff7ff50000)
Изучай. Увидимся!
