Система Linux Dlopen на C

Sistema Linux Dlopen Na C



Библиотечная функция dlopen() — очень полезная функция языка C. Функция загружает библиотеку в память после открытия новой. Обычно мы используем его для загрузки библиотечных символов, неизвестных во время компиляции. Dlopen() — это функция, которая используется в наших программах. Библиотека DL реализует dlopen(), определенную в Dlfcn.h. Для функции dlopen требуются два параметра: имя файла библиотеки и флаг. Имя файла — это динамическая библиотека, и оно определяет, будут ли сразу вычисляться зависимости библиотеки. dlopen() возвращает «дескриптор», который следует рассматривать как непрозрачное значение, и другие операции библиотеки DL используют его. Если попытка загрузки не удалась, dlopen() возвращает NULL. Но dlopen() возвращает один и тот же дескриптор файла, если он загружает одну и ту же библиотеку много раз.

При использовании функции dlopen компилятор не проверяет наличие потенциальных ошибок, поскольку ему неизвестны типы и прототипы, которые мы используем. Развертывание функции dlopen для стандартной загрузки, похоже, не способствует этому, за исключением нескольких незначительных ситуаций. Кстати, это способ улучшить самоанализ. Когда общий модуль в настоящее время используется другой программой, оптимизация размещения памяти не особенно заинтересована в условной загрузке. Объем памяти не увеличивается при загрузке ранее использовавшейся библиотеки. Отказ от мониторинга компилятора опасен и способствует хорошему написанию ошибок. Кроме того, нам не хватает возможной оптимизации компилятора.

Пример 1:

Теперь рассмотрим следующий пример, чтобы увидеть функциональность функции dlopen в языке C. На первом этапе мы загружаем несколько стандартных библиотек C. Здесь мы загружаем новую библиотеку «dlfcn.h», которая используется для определения макросов при построении аргумента режима dlopen.







Затем мы вводим в нашу программу еще одну библиотеку «gnu/lib-name.h». Файлы разделяемой библиотеки, включенные в GNU libc, обнаруживаются пользовательскими программами в соответствии с определяемыми ими макросами. Библиотека GNU C предлагает основные библиотеки для операционных систем GNU и GNU/Linux, а также для широкого спектра других систем на базе Linux. После этого у нас есть реализация основного метода. Внутри этого мы объявляем объект указателя «дескриптор» с ключевым словом void. Мы объявляем функцию синуса указателя с типом данных double. Существует еще одно объявление объекта указателя «error» для обработки ошибок.



После этого мы вызываем функцию dlopen внутри объекта «handle». dlopen принимает два аргумента: LIBM_SO и «RTLD_LAZY». Здесь «LIBM_SO» — это имя файла библиотеки, который предоставляет математические функции, такие как тригонометрические функции. Эта общая библиотека необходима, поскольку мы используем функцию синуса. «RTLD_LAZY» — это еще один аргумент, вызывающий функцию dlopen. Когда на данный символ ссылаются в первый раз, перемещения должны выполняться во время, определяемое реализацией.



Поскольку процесс может ссылаться не на каждый символ в исполняемом объектном файле, указание RTLD LAZY должно повысить производительность в реализациях, которые допускают динамическую привязку символов. Затем у нас есть условие if-else для обработки ошибок, когда объект дескриптора не может выполнить функцию dlopen. Мы вызываем dlerror, чтобы сбросить ошибку.





Функция dlerror() предоставляет строку с завершающим нулем, удобочитаемую и определяющую отчет о недавней ошибке, вызванной вызовом одного из вызовов API dlopen с момента последнего вызова dlerror. Затем мы приводим функцию следующим образом: «(*void**)(&sine)= dlsym(handle, sin)». Как это ни странно, приведение соответствует ISO C, что позволяет избежать предупреждений от компилятора. Мы используем функцию dlsym, которая получает путь к символу, указанному внутри модуля динамической ссылки, который доступен через функцию dlopen().

Кроме того, мы снова выполняем операцию if-else для стандартной ошибки, которая генерируется, когда dlerror() не равен NULL. Затем у нас есть оператор printf, в котором мы указываем вычисляемое значение синуса. На последнем шаге мы закрываем этот общий объект, вызывая dlclose для дескриптора, возвращаемого dlopen().



#include
#include
#include
#include

инт
главный ( инт аргк , уголь ** argv )
{
пустота * справиться ;
двойной ( * их ) ( двойной ) ;
уголь * ошибка ;

справиться знак равно открыть ( LIBM_SO , RTLD_LAZY ) ;
если ( ! справиться ) {
fprintf ( стдерр , '%s \n ' , ошибка ( ) ) ;
выход ( EXIT_FAILURE ) ;
}
ошибка ( ) ;

* ( пустота ** ) ( & их ) знак равно dlsym ( справиться , 'без' ) ;

если ( ( ошибка знак равно ошибка ( ) ) знак равно НУЛЕВОЙ ) {
fprintf ( стдерр , '%s \n ' , ошибка ) ;
выход ( EXIT_FAILURE ) ;
}

printf ( '%f \n ' , ( * их ) ( 4.0 ) ) ;
закрыть ( справиться ) ;
выход ( EXIT_SUCCESS ) ;
}

Мы используем параметр -ldl с командой компиляции C, так как это библиотека для связанного интерфейса dlopen, и она необходима. Когда выполняется выполнение файла dlopen, он отображает синусоидальное значение ранее заданного значения.

Пример 2:

Теперь возьмем еще один пример использования функции dlopen. Загружаем в нашу программу все необходимые библиотеки C для реализации кода dlopen. Затем мы запускаем нашу программу внутри основного метода. Здесь мы определяем строку с объявлением переменной «src». Затем мы объявляем переменные-указатели «strlen», «handle» и «error».

Затем мы вызываем переменную handle и запускаем функцию dlopen. Функция dlopen вводит разделяемую библиотеку «libstr.so» для функций обработки строк и флаг «RTLD_LAZY», который уже продемонстрирован в предыдущем примере. Мы вызываем функцию dlerror внутри переменной «error», чтобы сбросить ошибку, сгенерированную функцией dlopen. Если-иначе используется для проверки ошибок.

Затем мы получаем адрес функции strlen с помощью функции dlsym и проверяем ошибки при этом. После этого мы используем функцию printf для вызова функции strnlen для возврата длины заданной строки. В конце мы закрываем разделяемую библиотеку с помощью функции dlclose.

#include
#include
#include
#include
инт главный ( пустота )
{
уголь * источник знак равно 'Привет Линукс' ;
инт ( * стрлен ) ( константа уголь * ) ;
пустота * справиться ;
уголь * ошибка ;


справиться знак равно открыть ( './libstr.so' , RTLD_LAZY ) ;
ошибка знак равно ошибка ( ) ;
если ( ! справиться || ошибка знак равно НУЛЕВОЙ ) { printf ( 'Попытка загрузки библиотеки не удалась! \n %s \n ' , ошибка ) ;
возвращаться - 1 ; }

стрлен знак равно dlsym ( справиться , 'стрлен' ) ;
ошибка знак равно ошибка ( ) ;
если ( ! стрлен || ошибка == НУЛЕВОЙ ) { printf ( '%s \n ' , ошибка ) ; возвращаться - 1 ; }

printf ( 'Длина строки: %d \n ' , стрлен ( источник ) ) ;
закрыть ( справиться ) ;
возвращаться 0 ;
}

Мы используем следующую команду для выполнения данной программы. Здесь флаг -lstr используется для функции длины строки, а ldl используется для библиотечного файла dlopen. Скомпилированная программа дает длину строки, как показано в оболочке:

Вывод

В этой статье представлена ​​информация о функции dlopen языка C. У нас есть краткое введение в функцию dlopen. Затем мы реализовали два примера. Функция возвращает идентификатор, определяющий открытую библиотеку. Затем с помощью этого идентификатора и функции dlsym определяются адреса функций внутри открытой библиотеки. Адрес функции в библиотеке, которая уже была открыта с помощью dlopen, можно найти с помощью функции dlsym.