Linux Dlopen System w C

Linux Dlopen System W C



Funkcja biblioteczna dlopen() jest bardzo przydatną funkcją w języku C. Funkcja wczytuje bibliotekę do pamięci po otwarciu nowej. Zwykle używamy go do ładowania symboli bibliotecznych, które są nieznane w czasie kompilacji. Dlopen() to funkcja używana w naszych programach. Biblioteka DL implementuje funkcję dlopen(), zdefiniowaną w Dlfcn.h. Dla funkcji dlopen wymagane są dwa parametry: nazwa pliku biblioteki i flaga. Nazwa pliku jest biblioteką dynamiczną i określa, czy zależności biblioteki są obliczane od razu. dlopen() zwraca „uchwyt”, który powinien być traktowany jako nieprzezroczysta wartość i inne operacje na bibliotekach DL używają tego. Jeśli próba załadowania się nie powiodła, dlopen() zwraca NULL. Ale dlopen() zwraca ten sam uchwyt pliku, jeśli wielokrotnie ładuje tę samą bibliotekę.

Korzystając z funkcji dlopen, kompilator nie sprawdza potencjalnych błędów, ponieważ nie jest świadomy typów i prototypów, których używamy. Wdrażanie funkcji dlopen do standardowego ładowania nie wydaje się być przez nią promowane, z wyjątkiem kilku drobnych sytuacji. Nawiasem mówiąc, jest to podejście do poprawy introspekcji. Gdy współdzielony moduł jest aktualnie używany przez inny program, optymalizacja układu pamięci nie jest szczególnie zainteresowana ładowaniem warunkowym. Zużycie pamięci nie zwiększa się po załadowaniu poprzednio używanej biblioteki. Unikanie monitorowania kompilatora jest niebezpieczne i ułatwia pisanie błędów. Dodatkowo brakuje nam możliwej optymalizacji kompilatora.

Przykład 1:

Rozważmy teraz następujący przykład, aby zobaczyć funkcjonalność funkcji dlopen w języku C. W pierwszym kroku ładujemy kilka standardowych bibliotek C. Tutaj ładujemy nową bibliotekę „dlfcn.h”, która służy do definiowania makr podczas konstruowania argumentu trybu dlopen.







Następnie wprowadzamy kolejną bibliotekę do naszego programu „gnu/lib-name.h”. Pliki bibliotek współdzielonych zawarte w GNU libc są znajdowane przez programy użytkownika zgodnie ze zdefiniowanymi przez niego makrami. Biblioteka GNU C oferuje podstawowe biblioteki dla systemów operacyjnych GNU i GNU/Linux, a także szeroką gamę innych systemów opartych na Linuksie. Następnie mamy implementację metody głównej. Wewnątrz tego deklarujemy obiekt wskaźnika „handle” ze słowem kluczowym void. Deklarujemy funkcję wskaźnika sinus, która ma typ danych double. Istnieje inna deklaracja obiektu wskaźnika „error” do obsługi błędów.



Następnie wywołujemy funkcję dlopen wewnątrz obiektu „uchwyt”. Dlopen przyjmuje dwa argumenty: LIBM_SO i „RTLD_LAZY”. Tutaj „LIBM_SO” to nazwa pliku biblioteki, który zapewnia funkcje matematyczne, takie jak funkcje trygonometryczne. Ta biblioteka współdzielona jest wymagana, ponieważ używamy funkcji sinus. „RTLD_LAZY” to kolejny argument, który wywołuje funkcję dlopen. Kiedy dany symbol jest przywoływany po raz pierwszy, relokacje muszą być przeprowadzane w czasie określonym przez implementację.



Ponieważ proces może nie odwoływać się do każdego symbolu w wykonywalnym pliku obiektowym, określenie RTLD LAZY powinno zwiększyć wydajność w implementacjach, które umożliwiają dynamiczne wiązanie symboli. Następnie mamy warunek if-else dla obsługi błędów, gdy obiekt uchwytu nie wykona funkcji dlopen. Nazywamy dlerror, aby usunąć błąd.





Funkcja dlerror() udostępnia łańcuch zakończony znakiem null, który jest czytelny dla człowieka i określa raportowanie ostatniego błędu spowodowanego wywołaniem jednego z wywołań funkcji API dlopen od ostatniego wywołania funkcji dlerror. Następnie rzutujemy funkcję tak: „(*void**)(&sine)= dlsym(uchwyt, sin)”. Ponieważ jest to dziwne, rzutowanie jest zgodne z ISO C, co pozwala uniknąć ostrzeżeń kompilatora. Używamy funkcji dlsym, która pobiera ścieżkę do symbolu określonego w module łącza dynamicznego, który jest dostępny za pośrednictwem funkcji dlopen().

Wykonujemy również operację if-else ponownie dla standardowego błędu, który jest generowany, gdy dlerror() nie ma wartości NULL. Następnie mamy instrukcję printf, w której określamy wartość sinusa do obliczenia. W ostatnim kroku zamykamy ten współdzielony obiekt, wywołując dlclose dla uchwytu zwróconego przez dlopen().



#włącz
#include
#include
#include

int
Główny ( int argc , zwęglać ** argv )
{
próżnia * uchwyt ;
podwójnie ( * ich ) ( podwójnie ) ;
zwęglać * błąd ;

uchwyt = dlopen ( LIBM_SO , RTLD_LAZY ) ;
jeśli ( ! uchwyt ) {
fprintf ( stderr , '%s \n ' , dlerror ( ) ) ;
Wyjście ( EXIT_FAILURE ) ;
}
dlerror ( ) ;

* ( próżnia ** ) ( & ich ) = dlsym ( uchwyt , 'bez' ) ;

jeśli ( ( błąd = dlerror ( ) ) != ZERO ) {
fprintf ( stderr , '%s \n ' , błąd ) ;
Wyjście ( EXIT_FAILURE ) ;
}

printf ( '%f \n ' , ( * ich ) ( 4.0 ) ) ;
dlclose ( uchwyt ) ;
Wyjście ( EXIT_SUCCESS ) ;
}

Używamy opcji -ldl z poleceniem kompilacji C, ponieważ jest to biblioteka dla połączonego interfejsu dlopen i jest wymagana. Kiedy wykonywany jest plik dlopen, wyświetla wartość sinus poprzednio podanej wartości.

Przykład 2:

Weźmy teraz inny przykład użycia funkcji dlopen. Nasz program ładujemy ze wszystkimi wymaganymi bibliotekami C do implementacji kodu dlopen. Następnie uruchamiamy nasz program wewnątrz metody głównej. Tutaj definiujemy ciąg znaków z deklaracją zmiennej „src”. Następnie deklarujemy zmienne wskaźnikowe „strlen”, „handle” i „error”.

Następnie wywołujemy zmienną handle i wdrażamy funkcję dlopen. Funkcja dlopen wprowadza bibliotekę współdzieloną „libstr.so” dla funkcji obsługi ciągów znaków i flagę „RTLD_LAZY”, co zostało już zademonstrowane w poprzednim przykładzie. Wywołujemy funkcję dlerror wewnątrz zmiennej „error”, aby usunąć błąd wygenerowany przez funkcję dlopen. Jeśli-else jest wykorzystywane do sprawdzania błędów.

Następnie uzyskujemy adres funkcji strlen za pomocą funkcji dlsym i weryfikujemy przy tym błędy. Następnie używamy funkcji printf do wywołania funkcji strnlen w celu zwrócenia długości podanego ciągu. Na koniec zamykamy bibliotekę współdzieloną funkcją dlclose.

#włącz
#include
#include
#include
int Główny ( próżnia )
{
zwęglać * src = 'Witaj Linuksie' ;
int ( * strlen ) ( stały zwęglać * ) ;
próżnia * uchwyt ;
zwęglać * błąd ;


uchwyt = dlopen ( „./libstr.so” , RTLD_LAZY ) ;
błąd = dlerror ( ) ;
jeśli ( ! uchwyt || błąd != ZERO ) { printf ( „Próba ładowania biblioteki nie powiodła się! \n %s \n ' , błąd ) ;
zwrócić - 1 ; }

strlen = dlsym ( uchwyt , „zmęczyć” ) ;
błąd = dlerror ( ) ;
jeśli ( ! strlen || błąd == ZERO ) { printf ( '%s \n ' , błąd ) ; zwrócić - 1 ; }

printf ( 'Długość ciągu to:%d \n ' , strlen ( src ) ) ;
dlclose ( uchwyt ) ;
zwrócić 0 ;
}

Do wykonania danego programu używamy następującego polecenia. Tutaj flaga -lstr jest używana dla funkcji długości łańcucha, a ldl jest używany dla pliku biblioteki dlopen. Skompilowany program podaje długość ciągu, jak pokazano w powłoce:

Wniosek

W tym artykule podano informacje dotyczące funkcji dlopen języka C. Mamy krótkie wprowadzenie do funkcji dlopen. Następnie zaimplementowaliśmy dwa przykłady. Funkcja zwraca identyfikator definiujący otwartą bibliotekę. Adresy funkcji wewnątrz otwartej biblioteki są następnie określane za pomocą tego identyfikatora i funkcji dlsym. Adres funkcji w bibliotece, która została już otwarta za pomocą dlopen, można znaleźć za pomocą funkcji dlsym.