Читаем Linux API. Исчерпывающее руководство полностью

Версионная метка VER_2 также указывает на то, что к ней будет привязана новая функция pqr(), которая экспортируется библиотекой. Если не объявить функцию pqr() таким способом, то ключевое слово local, наследованное меткой VER_2 от VER_1, сделает ее невидимой за пределами библиотеки. Стоит также отметить: если бы мы просто опустили ключевое слово local, то символы xyz_old() и xyz_new() тоже были бы экспортированы (обычно это нежелательно).

Теперь соберем новую версию нашей библиотеки уже привычным способом:

$ gcc — g — c — fPIC — Wall sv_lib_v2.c

$ gcc — g — shared — o libsv.so sv_lib_v2.o — Wl, — version-script,sv_v2.map

Теперь можно создать новую программу, p2, которая использует новое определение функции xyz(); при этом программа p1 будет применять ее старую версию.

$ gcc — g — o p2 sv_prog.c libsv.so

$ LD_LIBRARY_PATH=. /p2

v2 xyz Использует xyz@VER_2

$ LD_LIBRARY_PATH=. /p1

v1 xyz Использует xyz@VER_1

Зависимости версионной метки записываются в исполняемый файл на этапе статической компоновки. Если вывести с помощью команды objdump — t таблицы символов для обеих программ, то получим разные зависимости:

$ objdump — t p1 | grep xyz

08048380 F *UND* 0000002e xyz@@VER_1

$ objdump — t p2 | grep xyz

080483a0 F *UND* 0000002e xyz@@VER_2

Похожую информацию можно также получить, задействуя команду readelf — s.

Дополнительные сведения о версионировании символов можно найти на https://www.akkadia.org/drepper/symbol-versioning или воспользовавшись командой info ld scripts.

42.4. Инициализация и финализация функций

Можно определить одну или несколько функций, которые будут автоматически вызываться при загрузке и выгрузке разделяемой библиотеки. Это позволит выполнять действия по инициализации и финализации во время работы с библиотеками. Функции инициализации и финализации вызываются вне зависимости от того, загружена библиотека автоматически или вручную, используя интерфейс dlopen (см. раздел 42.1).

Функции инициализации и финализации определяются с помощью атрибутов constructor и destructor компилятора gcc. Любую функцию, которую нужно выполнить при загрузке библиотеки, следует определить таким образом:

void __attribute__ ((constructor)) some_name_load(void)

{

/* Код инициализации */

}

Функции выгрузки имеют похожее определение:

void __attribute__ ((destructor)) some_name_unload(void)

{

/* Код финализации */

}

Вместо some_name_load() и some_name_unload() можно использовать любые другие имена на ваш выбор.

Атрибуты constructor и destructor компилятора gcc можно также применять для создания функций инициализации и финализации в главной программе.

Функции _init() и _fini()

Существует и более старый способ инициализации и финализации разделяемых библиотек. Он заключается в создании внутри библиотеки двух функций, _init() и _fini(). Функция void _init(void) содержит код, который выполняется, когда библиотека впервые загружается процессом. Код функции void _fini(void) выполняется при выгрузке библиотеки.

Создав функции _init() и _fini(), нужно указать во время компиляции разделяемой библиотеки параметр gcc — nostartfiles, чтобы не дать компоновщику включить их стандартные версии (при желании можно выбрать для них другие имена, воспользовавшись параметрами — Wl, — init и — Wl, — fini).

Применение функций _init() и _fini() считается устаревшей практикой. Им на смену пришли атрибуты constructor и destructor компилятора gcc, которые среди прочих преимуществ позволяют определить несколько функций инициализации и финализации.

42.5. Предварительная загрузка разделяемых библиотек

Во время тестирования иногда может понадобиться переопределить функции (и другие символы), которые в обычных условиях были бы найдены динамическим компоновщиком на основе правил, описанных в разделе 41.11. Для этого переменной среды LD_PRELOAD можно присвоить строку с именами разделяемых библиотек, которые следует загрузить раньше других (имена разделяются двоеточиями). Поскольку данные библиотеки загружаются в первую очередь, их функции, запрашиваемые программой, будут использоваться автоматически, переопределяя любые одноименные символы, которые в противном случае пришлось бы искать динамическому компоновщику. Представьте, к примеру, что наша программа вызывает функции x1() и x2(), определенные в библиотеке libdemo. Запустив эту программу, мы увидим следующий вывод:

$ ./prog

Called mod1-x1 DEMO

Called mod2-x2 DEMO

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

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных