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

В поправке SUSv3 TC1 также отмечается, что из-за необходимости применения операции *(void **) будущая версия стандарта может содержать отдельный программный интерфейс, похожий на dlsym() и предназначенный для работы с указателями на данные и функции. Однако в стандарте SUSv4 никаких подобных изменений не предусмотрено.

Использование псевдодескрипторов в сочетании с функцией dlsym()

Вместо дескрипторов, возвращаемых вызовом dlopen(), аргументу handle функции dlsym() можно передать один из следующих псевдодескрипторов.

• RTLD_DEFAULT — поиск символа начинается с главной программы, после чего проходит по списку всех разделяемых библиотек, в том числе и загруженных динамически с помощью вызова dlopen() с флагом RTLD_GLOBAL. Это аналогично стандартному алгоритму поиска, который применяется динамическим компоновщиком.

• RTLD_NEXT — поиск символа выполняется по библиотекам, загруженным после вызова dlsym(). Это может пригодиться при создании функций-оберток, чьи имена совпадают с именами каких-то других функций, определенных где-либо. Например, можно определить в главной программе собственную версию функции malloc() (возможно, ведущую учет выделяемой памяти), которая будет вызывать одноименный оригинал; для этого она должна получить его адрес с помощью вызова func = dlsym(RTLD_NEXT, "malloc").

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

Пример программы

Применение программного интерфейса dlopen продемонстрировано в листинге 42.1. Эта программа принимает два аргумента командной строки: имя разделяемой библиотеки, которую нужно загрузить, и имя функции, которую нужно вызвать из этой библиотеки. Ниже показаны примеры запуска данной программы:

$ ./dynload./libdemo.so.1 x1

Called mod1-x1

$ LD_LIBRARY_PATH=. /dynload libdemo.so.1 x1

Called mod1-x1

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

Листинг 42.1. Использование программного интерфейса dlopen

shlibs/dynload.c

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

void *libHandle; /* Дескриптор для разделяемой библиотеки */

void (*funcp)(void); /* Указатель на функцию без аргументов */

const char *err;

if (argc!= 3 || strcmp(argv[1], "-help") == 0)

usageErr("%s lib-path func-name\n", argv[0]);

/* Загружаем разделяемую библиотеку и получаем дескриптор

для ее дальнейшего использования */

libHandle = dlopen(argv[1], RTLD_LAZY);

if (libHandle == NULL)

fatal("dlopen: %s", dlerror());

/* Ищем в библиотеке символ с именем, заданным в argv[2] */

(void) dlerror(); /* Очищаем ошибки с помощью dlerror() */

*(void **) (&funcp) = dlsym(libHandle, argv[2]);

err = dlerror();

if (err!= NULL)

fatal("dlsym: %s", err);

/* Если адрес, возвращенный dlsym(), не равен NULL, пытаемся вызвать

это значение как функцию, которая не принимает аргументов */

if (funcp == NULL)

printf("%s is NULL\n", argv[2]);

else

(*funcp)();

dlclose(libHandle); /* Закрываем библиотеку */

exit(EXIT_SUCCESS);

}

shlibs/dynload.c

42.1.4. Закрытие разделяемой библиотеки: dlclose()

Функция dlclose() закрывает библиотеку.

include

int dlclose(void *handle);

Возвращает 0 при успешном завершении или -1 при ошибке

Функция dlclose() декрементирует системный счетчик открытых ссылок на библиотеку, на которую указывает дескриптор handle. Когда счетчик доходит до нуля и ни один символ библиотеки больше не используется извне, библиотека выгружается. Такая же процедура выполняется (рекурсивно) для всех библиотек, входящих в ее дерево зависимостей. Во время завершения процесса вызов dlclose() автоматически выполняется для всех библиотек.

Начиная с glibc 2.2.3, разделяемая библиотека может совершить вызов atexit() (или on_exit()), чтобы установить функцию, которая будет автоматически запускаться при ее выгрузке.

42.1.5. Получение информации о загруженных символах: dladdr()

Возвращает структуру с информацией об адресе, заданном в аргументе addr (который обычно берется из ранее выполненного вызова dlsym()).

#define _GNU_SOURCE

#include

int dladdr(const void *addr, Dl_info *info);

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

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

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

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

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

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

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

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

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