Чтение онлайн

ЖАНРЫ

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

% gcc -о compute compute.c -lm

При компоновке программ, написанных на C++, компилятор

c++
или
g++
автоматически подключает к ним стандартную библиотек языка C++:
libstdc++
.

2.3.4. Зависимости между библиотеками

Библиотеки часто связаны одна с другой. Например, во многих Linux-системах есть библиотека

libtiff
, содержащая функции чтения и записи графических файлов формата TIFF. Она, в свою очередь, использует библиотеки
libjpeg
(подпрограммы обработки JPEG-изображений) и
libz
(подпрограммы сжатия).

В

листинге 2.9 показана небольшая программа, использующая функции библиотеки
libtiff
для работы с TIFF-файлом.

Листинг 2.9. (tifftest.c) Применение библиотеки
libtiff

#include <stdio.h>

#include <tiffio.h>

int main(int argc, char** argv) {

 TIFF* tiff;

 tiff = TIFFOpen(argv[1], "r");

 TIFFClose(tiff);

 return 0;

}

При компиляции этого файла необходимо указать флаг

– ltiff
:

% gcc -о tifftest tifftest.c -ltiff

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

/usr/lib/libtiff.so
. В связи с тем что она обращается к библиотекам
libjpeg
и
libz
(одна совместно используемая библиотека может ссылаться на другие аналогичные библиотеки, от которых она зависит), будут также подключены их совместно используемые версии. Чтобы проверить это, воспользуемся командой
ldd
:

% ldd tifftest

 libtiff.so.3 => /usr/lib/libtiff.so.3 (0x4001d000)

 libc.so.6 => /lib/libc.so.6 (0x40060000)

 libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x40155000)

 libz.so.1 => /usr/lib/libz.so.1 (0x40174000)

 /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

В противоположность этому статические библиотеки не могут указывать на другие библиотеки. Если попытаться подключить к программе статическую версию библиотеки

libtiff
, указав в командной строке опцию
– static
, компоновщик столкнется с нераспознаваемыми символическими константами:

% gcc -static -о tifftest tifftest.с -ltiff

/usr/bin/../lib/libtiff.a(tif_jpeg.o): In function

'TIFFjpeg_error_exit':

tif_jpeg.о(.text+0x2a): undefined reference to 'jpeg_abort'

/usr/bin/../lib/libtiff.a (tif_jpeg.o): In function

'TIFFjpeg_create_compress':

tif_jpeg.o(.text+0x8d): undefined reference to 'jpeg_std_error'

tif_jpeg.o(.text+0xcf): undefined reference to

'jpeg_CreateCompress'

...

В случае статической компоновки программы нужно самостоятельно указать две другие библиотеки:

% gcc -static -o tifftest tifftest.c -ltiff -ljpeg -lz

Иногда между двумя библиотеками образуется взаимная зависимость. Другими словами, первый архив ссылается на символические константы, определенные во втором архиве, и наоборот. Такая ситуация, как правило, является следствием неправильного проектирования. В этом случае нужно указать в командной строке одну и ту же библиотеку несколько раз. Компоновщик просмотрит библиотеку столько раз, сколько она присутствует в командной строке. Рассмотрим пример:

% gcc -o app арр.о -lfoo -lbar -lfoo

Теперь,

даже если библиотека
libfoo.a
ссылается на символические константы в библиотеке
libbar.a
и наоборот, программа будет успешно скомпонована.

2.3.5. Преимущества и недостатки библиотек

Познакомившись со статическими архивами и совместно используемыми библиотеками. читатели, очевидно, задумались: какие же из них лучше использовать? Есть несколько важных моментов, о которых следует помнить.

Большим преимуществом совместно используемой библиотеки является то. что она экономит место на диске при инсталляции программы. Когда устанавливаются десять программ и все они работают с одной и той же библиотекой, экономия может оказаться весьма существенной, тогда как статический архив будет включен во все десять программ. Уменьшается также время загрузки, если программа загружается из Internet.

С этим связано еще одно преимущество совместно используемых библиотек: пользователи могут обновлять библиотеки, не затрагивая связанные с ними программы. Предположим, к примеру, что была создана библиотека, содержащая функции управления HTTP- соединениями. Потенциально с ней может работать множество программ. Если впоследствии в библиотеке обнаружится ошибка, достаточно будет просто заменить ее файл, и все программы, использующие данную библиотеку, немедленно обновятся. Не придется выполнять перекомпоновку всех программ, как в случае статического архива.

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

Если библиотеки не должны инсталлироваться в каталог

/lib
или
/usr/lib
, нужно дважды подумать, стоит ли их делать совместно используемыми. (Библиотеки нельзя помещать в указанные каталоги, если предполагается, что программу будут инсталлировать пользователи, не имеющие привилегий системного администратора.) В частности, прием с флагом
– Wl,-rpath
не будет работать, поскольку не известно, где именно окажутся библиотеки. А просить пользователей устанавливать переменную
LD_LIBRARY_PATH
— не выход из положения, так как это означает для них выполнение дополнительного (для некоторых — не самого тривиального) действия.

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

2.3.6. Динамическая загрузка и выгрузка

Иногда на этапе выполнения программы требуется загрузить некоторый код без явной компоновки. Рассмотрим приложение, поддерживающее подключаемые модули: Web-броузер. Архитектура броузера позволяет сторонним разработчикам создавать дополнительные модули, расширяющие функциональные возможности броузера. Модуль реализуется в виде совместно используемой библиотеки и размещается в заранее известном каталоге. Броузер автоматически загружает код из этого каталога.

Для этих целей в Linux существует специальная функция

dlopen
. Например, открыть библиотеку
libtest.so
можно следующим образом:

dlopen("libtest.so", RTLD_LAZY)

Второй параметр — это флаг, определяющий способ привязки символических констант в библиотеке. Данная установка подходит в большинстве случаев. Подробнее узнать о ней можно в документации.

Объявление функций работы с динамическими библиотеками находится в файле

<dlfcn.h>
. Использующие их программы должны компоноваться с флагом
– ldl
, обеспечивающим подключение библиотеки
libdl
.

Поделиться с друзьями: