Библиотеки

Библиотеки

Oleg

Практически все программы Linux используют одни и те же стандартные функции, например для обращения к файлам, вывода изображения на экран, поддержки X и т. д. Было бы нецелесообразно записывать все эти функции прямо в коде не самой большой программы — тогда файлы программ стали бы гигантскими. Вместо этого большинство программ Linux обращается к так называемым разделяемым биб­лиотекам: при выполнении программы автоматически загружаются и требуемые библиотеки. В чем заключается преимущество? Если несколько программ используют функции одной и той же библиотеки, то эту библиотеку необходимо загрузить лишь один раз.

Библиотеки играют ключевую роль, когда определяется, какие программы можно будет выполнять на компьютере. Если не хватает одной-единственной биб­лиотеки (или в наличии имеется только старая версия), то непосредственно при запуске программы выводится сообщение об ошибке. Чтобы в таких случаях вы не оставались на произвол судьбы в недрах Linux, в этой статье я предоставлю базовую информацию по библиотекам.

Динамическая связь программ с помощью ссылок. Большинство программ Linux при работе обращаются к разделяемым библиотекам. Так экономится место на диске (ведь двоичные файлы программ компактны) и меньше нагружается оперативная память (поскольку один и тот же код не требуется грузить многократно). Замечание для программистов, работающих с Windows: разделяемые библиотеки сравнимы с DLL — динамически подключаемыми библиотеками.

Программы, связанные статическими ссылками. При компилировании программ библиотеки можно связывать и статическими ссылками. Это значит, что библиотечные функции интегрируются прямо в программный код. При этом программный файл увеличивается в размерах, зато не зависит от каких-либо библиотек. Это практично, если программу требуется передавать с компьютера на компьютер — тогда она будет работать «с ходу», независимо от того, какие библиотеки уже установлены на компьютере. Иногда статическими ссылками связываются и некоторые простейшие команды для администрирования, чтобы такие команды оставались доступны и тогда, когда разделяемые библиотеки невозможно использовать из-за ошибок в конфигурации.

Форматы и версии библиотек

На протяжении истории Linux в библиотеки не раз вносились изменения, которые были столь же фундаментальны, сколь и несовместимы друг с другом. К числу таких изменений относится, например, замена формата A.OUT на ELF или замена библиотеки libc 5 версии на glibc версии 2.n, причем к последней можно обращаться и как libc 6.

В обоих случаях замены библиотек были технически оправданны. Новые форматы или версии позволяют с большей легкостью управлять библиотеками и функциями, обеспечивают более полную совместимость различных платформ Linux (Intel, Sun-Sparc, DEC-Alpha) и пр.

Однако при замене возникают проблемы, связанные с тем, что скомпилированные программы могут выполняться только тогда, когда в системе установлены нужные библиотеки и система может их найти. Если вы попытаетесь выполнить программу для glibc в старом дистрибутиве, в котором glibc не поддерживается, то получите загадочное сообщение об ошибке следующего содержания:

root# programmxy
bash: /usr/local/bin/programmxy: No such file or directory

Из-за того, что в настоящее время имеются проблемы с поддержкой библиотеки glibc, готовящаяся к выходу версия Debian Squeeze предположительно будет использовать не оригинальную библиотеку glibc, а полностью совместимую биб­лиотеку eglibc. Эта замена не причинит неудобств ни конечным пользователям, ни разработчикам.

Автоматическая загрузка библиотек

Если вы работаете с Linux только как пользователь, а не как программист, то вы столкнетесь с библиотеками лишь в тот момент, когда какой-то из них будет недоставать. Обычно такие проблемы возникают, если вы постепенно устанавливаете новую программу. При попытке запустить ее выводится сообщение об ошибке, указывающее на отсутствие определенной библиотеки. Часто актуальные версии программ ссылаются на новейшие версии соответствующих библиотек, которые у вас, возможно, еще не установлены. Со старыми программами вероятен прямо противоположный случай. Может быть, они еще ссылаются на устаревшие библиотеки, которые уже не поддерживаются в вашем дистрибутиве.

Определение списка библиотек

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

user$ ldd /bin/cp
linux-vdso.so.1 => (0x00007fff3bb59000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f8ab9acc000)
librt.so.1 => /lib64/librt.so.1 (0x00007f8ab98c4000)
libacl.so.1 => /lib64/libacl.so.1 (0x00007f8ab96bb000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007f8ab94b6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8ab9127000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f8ab8f23000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8ab9cea000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8ab8d06000)

Что касается программ X-, KDE- и Gnome, здесь список библиотек гораздо обширнее. Именно по этой причине эти программы запускаются достаточно долго.

Если ldd возвратит результат not a dynamic executable, то вы имеете дело с программой, которая уже содержит все необходимые библиотеки, то есть это программа со статическими ссылками.

Названия библиотек

Краткая информация о наименованиях библиотек: окончание .so указывает, что мы имеем дело с разделяемой библиотекой, окончание .а определяет статическую библиотеку. Цифра указывает номер основной версии. Например, ls требует биб­лиотеку libc версии 6.

Каталоги, в которых обычно располагаются библиотеки (например, /lib, /usr/lib, /usr/local/lib, /usr/X11R6/lib и /opt/lib), часто содержат ссылки, связывающие основную версию библиотеки с той, что установлена на вашем компьютере. Так, для cp требуется библиотека ld-linux-x68-64.so.2. Но на самом деле на компьютере установлена версия ld-2.14.so, совместимая «снизу вверх».

user$ ls -l /lib/ld*
/lib/ld-2.14.1.so

/lib/ld-linux.so.2 -> ld-2.14.1.so

Запуск программ

При запуске программ нужно найти и загрузить все библиотеки — за это отвечает так называемый компоновщик времени выполнения. При этом учитываются все каталоги, указанные в переменной окружения LD_LIBRARY_PATH. Эти каталоги разделяются двоеточиями.

Кроме того, компоновщик интерпретирует файл /etc/ld.so.cache. Это двоичный файл, содержащий всю важную информацию о библиотеке (номера версий, пути доступа и т. д.). Он нужен только для того, чтобы сэкономить время, которое компоновщик в противном случае потратил бы на поиск библиотек.

Файл /etc/ld.so.cache создается программой ldconfig, которая, в свою очередь, интерпретирует /etc/ld.so.conf. В этом файле обычно содержится список всех библиотечных каталогов или список ссылок на другие файлы с каталогами (каталоги /lib и /usr/lib учитываются в любом случае и поэтому отсутствуют в ld.so.conf или других конфигурационных файлах. Если кроме /lib и /usr/lib не придется учитывать никаких каталогов, то ld.so.conf можно вообще опустить).

В некоторых дистрибутивах команда ldconfig выполняется при каждом запуске компьютера, чтобы гарантировать максимально обновленное состояние файла кэша. Ее всегда нужно выполнять в тех случаях, когда вы вручную устанавливаете новую библиотеку, иначе система не увидит библиотек. Если библиотеки находятся в новом каталоге, нужно соответствующим образом дополнить файл /etc/ld.so.conf. При установке пакетов с библиотеками эти задачи обычно выполняет менеджер пакетов.

32- и 64-битные библиотеки

Большинство распространенных дистрибутивов в настоящее время существуют как минимум в двух вариантах сборки: для 32-битных процессоров, совместимых с Intel/AMD, и для 64-битных процессоров, совместимых с Intel/AMD. Разумеется, для 32-битных процессоров предусмотрены только 32-битные библиотеки. Однако, к сожалению, того же нельзя сказать о 64-битных дистрибутивах: были и остаются программы, которые не компилируются для 64-битных систем. Наиболее известная программа такого рода — Acrobat Reader компании Adobe.

/lib и /lib64. Для выполнения 32-битных программ в 64-битных дистрибутивах вам потребуются 32-битные библиотеки. Чтобы можно было избежать конфликтов, библиотеки устанавливаются в различные каталоги. Среди профессионалов в Linux этот метод называется мультиархитектура, или биархитектура, так как параллельно поддерживается несколько (или две) архитектуры процессоров. В большинстве дистрибутивов встречаются каталоги /lib32 или /lib64, позволяющие не смешивать библиотеки с различной разрядностью. Такая двойственность, разумеется, связана с определенными недостатками: при установке многочисленных библиотек в двух экземплярах тратится больше дискового пространства, кроме того, при этом осложняется техническая поддержка.

В сравнительно старых версиях Debian и Ubuntu для установки в 64-битных системах базы из 32-битных библиотек использовался, как правило, мета-пакет ia32-libs.

Multiarch. В настоящее время применяется новый подход, при котором в /usr/lib создаются подкаталоги для каждого конкретного варианта архитектуры процессора, например /usr/lib/x86_64-linux-gnu.

Идея Multiarch охватывает не только организацию путей каталогов, но и принципы управления пакетами. Например, при необходимости она должна предоставлять возможность устанавливать один и тот же пакет и в 32-битной, и в 64-битной версии. Чтобы четко различать такие варианты, можно указывать для пакета вариант архитектуры с помощью двоеточия, например gvfs:i386 (означает 32-битную версию пакета gvfs). Работа по проверке зависимостей в таком случае удваивается (соответственно, проверяются зависимости для 32-битных и 64-битных версий). Команда dpkg уже хорошо поддерживает работу по принципу Multiarch.

Из-за появления концепции Multiarch пакет ia32-libs окончательно устаревает. Но он по-прежнему выпускается ради обеспечения совместимости. Но теперь он определяет только зависимость с ia32-libs-multiarch . То есть речь идет исключительно о 32-битном пакете.

Предварительное связывание

При запуске программы, которая обращается к динамическим библиотекам, нужно установить соединение между программой и библиотеками. Этот процесс именуется связыванием. При работе со сложными программами на связывание тратится немало времени.

Программа prelink может заранее выяснить информацию, необходимую для связывания. В первый раз этот процесс длится очень долго. При этом требуется просмотреть все исполняемые программы. Файл /etc/prelink.conf определяет, какие каталоги с программами и библиотеками учитывает prelink. Другие функции можно установить в /etc/sysconfig/prelink или /etc/default/prelink (Debian, Ubuntu).

В дальнейшем каждая подготовленная таким образом программа будет обращаться к своим библиотекам гораздо быстрее, а значит, и быстрее запускаться. Такое ускорение особенно заметно в OpenOffice или в программах KDE, на запуск которых теперь потребуется вполовину меньше времени, чем раньше. В любом случае данные предварительного связывания необходимо обновлять при каждом обновлении библиотеки.

Предварительное связывание имеет еще один недостаток — эта операция изменяет исполняемые файлы всех программ и библиотек. Кроме того, вы уже не сможете контролировать целостность таких файлов (то есть не сможете убедиться, что после установки файлы остались прежними). Когда угодно можно отменить любые изменения, внесенные в ходе предварительного связывания, с помощью команды prelink -ua. Базовая информация по предварительному связыванию сообщается в справке man.

Debian, Ubuntu. Чтобы пользоваться предварительным связыванием в Debian и Ubuntu, необходимо установить пакет prelink и задать в файле /etc/default/prelink настройку PRELINKING=yes. Предварительное связывание будет ежедневно выполняться в качестве одной из задач Cron.

Red Hat, Fedora. Функция предварительного связывания установлена по умолчанию. Данные регулярно обновляются (задача Cron /etc/cron.daily/prelink, конфигурационный файл /etc/sysconfig/prelink).

SUSE. Чтобы использовать предварительное связывание, необходимо установить пакет prelink и указать в файле /etc/sys-config/prelink настройку PRELINKING=yes. Затем prelink будет выполняться модулем YaST после установки любой новой программы или библиотеки (сценарий /sbin/conf.d/SuSEconfig.prelink).

Report Page