Système Linux Dlopen en C

Systeme Linux Dlopen En C



La fonction de bibliothèque dlopen() est une fonction très utile en langage C. La fonction charge la bibliothèque dans la mémoire après en avoir ouvert une nouvelle. Nous l'utilisons généralement pour charger les symboles de bibliothèque qui sont inconnus au moment de la compilation. Dlopen() est une fonction utilisée dans nos programmes. La bibliothèque DL implémente dlopen(), défini dans Dlfcn.h. Deux paramètres sont requis pour la fonction dlopen : le nom du fichier de bibliothèque et le drapeau. Le nom du fichier est une bibliothèque dynamique, et il définit si oui ou non les dépendances de la bibliothèque sont calculées immédiatement. Le dlopen() renvoie un 'handle' qui doit être considéré comme une valeur opaque et d'autres opérations de la bibliothèque DL l'utilisent. Si la tentative de chargement échoue, dlopen() renvoie NULL. Mais dlopen() renvoie le même descripteur de fichier s'il charge plusieurs fois la même bibliothèque.

Lors de l'utilisation de la fonction dlopen, le compilateur n'examine pas les erreurs potentielles car il ne connaît pas les types et les prototypes que nous utilisons. Le déploiement de la fonction dlopen pour le chargement standard ne semble pas en être favorisé, sauf pour quelques situations mineures. Soit dit en passant, c'est une approche pour améliorer l'introspection. Lorsque le module partagé est actuellement utilisé par un autre programme, l'optimisation de la disposition de la mémoire n'est pas particulièrement intéressée par le chargement conditionnel. L'empreinte mémoire n'augmente pas lorsqu'une bibliothèque précédemment utilisée est chargée. Éviter la surveillance du compilateur est dangereux et permet une bonne écriture de bogue. De plus, nous manquons de l'optimisation possible du compilateur.

Exemple 1:

Maintenant, considérons l'exemple suivant pour voir la fonctionnalité de la fonction dlopen dans le langage C. Dans la première étape, nous chargeons certaines bibliothèques standard C. Ici, nous chargeons la nouvelle bibliothèque 'dlfcn.h' qui est utilisée pour définir les macros tout en construisant l'argument du mode dlopen.







Ensuite, nous introduisons une autre bibliothèque dans notre programme 'gnu/lib-name.h'. Les fichiers de bibliothèque partagés inclus avec GNU libc sont trouvés par les programmes utilisateur en fonction des macros qu'il définit. La bibliothèque GNU C offre les bibliothèques fondamentales pour les systèmes d'exploitation GNU et GNU/Linux ainsi qu'une large gamme d'autres systèmes basés sur Linux. Après cela, nous avons la mise en œuvre de la méthode principale. À l'intérieur de cela, nous déclarons l'objet pointeur 'handle' avec le mot-clé void. Nous déclarons une fonction sinus de pointeur qui a le type de données double. Il existe une autre déclaration de l'objet pointeur 'error' pour la gestion des erreurs.



Après cela, nous invoquons la fonction dlopen à l'intérieur de l'objet 'handle'. Le dlopen prend deux arguments : LIBM_SO et 'RTLD_LAZY'. Ici, 'LIBM_SO' est le nom du fichier bibliothèque qui fournit des fonctions mathématiques comme les fonctions trigonométriques. Cette bibliothèque partagée est nécessaire car nous utilisons la fonction sinus. Le 'RTLD_LAZY' est un autre argument qui appelle la fonction dlopen. Lorsqu'un symbole donné est référencé pour la première fois, les relocalisations doivent être effectuées à un instant déterminé par l'implémentation.



Puisqu'un processus peut ne pas référencer chaque symbole dans un fichier objet exécutable, la spécification du RTLD LAZY devrait améliorer les performances sur les implémentations qui permettent la liaison dynamique des symboles. Ensuite, nous avons une condition if-else pour la gestion des erreurs lorsque l'objet handle ne parvient pas à exécuter la fonction dlopen. Nous appelons le dlerror pour effacer l'erreur.





La fonction dlerror() fournit une chaîne à terminaison nulle qui est lisible par l'homme et spécifie le rapport de l'erreur récente provoquée par un appel à l'un des appels d'API dlopen depuis le dernier appel dlerror. Ensuite, nous transcrivons la fonction comme suit : '(*void**)(&sine)= dlsym(handle, sin)'. Comme c'est étrange, le casting est conforme à l'ISO C qui évite les avertissements du compilateur. Nous utilisons la fonction dlsym qui obtient le chemin d'un symbole spécifié dans un module de lien dynamique accessible via une fonction dlopen().

De plus, nous effectuons à nouveau l'opération if-else pour l'erreur standard qui est générée lorsque dlerror() n'est pas NULL. Ensuite, nous avons une instruction printf où nous spécifions la valeur du sinus à calculer. Dans la dernière étape, nous fermons cet objet partagé en appelant dlclose pour le handle renvoyé par dlopen().



#include
#include
#include
#include

entier
principale ( entier argc , carboniser ** argv )
{
annuler * manipuler ;
double ( * les leurs ) ( double ) ;
carboniser * Erreur ;

manipuler = ouvrir ( LIBM_SO , RTLD_LAZY ) ;
si ( ! manipuler ) {
fprintf ( stderr , '%s \n ' , dlerror ( ) ) ;
sortir ( EXIT_FAILURE ) ;
}
dlerror ( ) ;

* ( annuler ** ) ( & les leurs ) = dlsym ( manipuler , 'sans pour autant' ) ;

si ( ( Erreur = dlerror ( ) ) != NUL ) {
fprintf ( stderr , '%s \n ' , Erreur ) ;
sortir ( EXIT_FAILURE ) ;
}

printf ( '%F \n ' , ( * les leurs ) ( 4.0 ) ) ;
dlfermer ( manipuler ) ;
sortir ( EXIT_SUCCESS ) ;
}

Nous utilisons l'option -ldl avec la commande de compilation C puisqu'il s'agit de la bibliothèque de l'interface liée dlopen et qu'elle est obligatoire. Lorsque l'exécution du fichier dlopen est faite, il affiche la valeur sinusoïdale de la valeur précédemment donnée.

Exemple 2 :

Maintenant, prenons un autre exemple d'utilisation de la fonction dlopen. Nous chargeons notre programme avec toutes les bibliothèques C nécessaires à l'implémentation du code dlopen. Ensuite, nous commençons notre programme à l'intérieur de la méthode principale. Ici, nous définissons la chaîne avec la déclaration de la variable « src ». Nous déclarons ensuite les variables de pointeur 'strlen', 'handle' et 'error'.

Ensuite, nous appelons la variable handle et déployons la fonction dlopen. La fonction dlopen saisit la bibliothèque partagée 'libstr.so' pour les fonctions de gestion des chaînes et le drapeau 'RTLD_LAZY' qui est déjà démontré dans l'exemple précédent. Nous invoquons la fonction dlerror dans la variable 'error' pour effacer l'erreur générée par la fonction dlopen. Le if-else est utilisé pour examiner les erreurs.

Ensuite, nous obtenons l'adresse de la fonction strlen en utilisant la fonction dlsym et vérifions les erreurs en faisant cela. Après cela, nous utilisons la fonction printf pour appeler la fonction strnlen afin de renvoyer la longueur de la chaîne donnée. Au final, on ferme la bibliothèque partagée avec la fonction dlclose.

#include
#include
#include
#include
entier principale ( annuler )
{
carboniser * src = 'Bonjour Linux' ;
entier ( * tendu ) ( constante carboniser * ) ;
annuler * manipuler ;
carboniser * Erreur ;


manipuler = ouvrir ( './libstr.so' , RTLD_LAZY ) ;
Erreur = dlerror ( ) ;
si ( ! manipuler || Erreur != NUL ) { printf ( 'Echec de la tentative de chargement de la bibliothèque ! \n %s \n ' , Erreur ) ;
revenir - 1 ; }

tendu = dlsym ( manipuler , 'strlen' ) ;
Erreur = dlerror ( ) ;
si ( ! tendu || Erreur == NUL ) { printf ( '%s \n ' , Erreur ) ; revenir - 1 ; }

printf ( 'La longueur de la chaîne est : %d \n ' , tendu ( src ) ) ;
dlfermer ( manipuler ) ;
revenir 0 ;
}

Nous utilisons la commande suivante pour l'exécution du programme donné. Ici, le drapeau -lstr est utilisé pour la fonction de longueur de chaîne et le ldl est utilisé pour le fichier de bibliothèque dlopen. Le programme compilé donne la longueur de la chaîne comme indiqué dans le shell :

Conclusion

Les informations concernant la fonction dlopen du langage C sont fournies dans cet article. Nous avons une brève introduction de la fonction dlopen. Ensuite, nous avons implémenté deux exemples. La fonction renvoie un identifiant qui définit la bibliothèque ouverte. Les adresses des fonctions à l'intérieur de la bibliothèque ouverte sont alors déterminées à l'aide de cet identifiant et de la fonction dlsym. L'adresse d'une fonction dans une bibliothèque qui a déjà été ouverte à l'aide de dlopen peut être trouvée à l'aide de la fonction dlsym.