Comment fonctionne la liaison statique sous Linux


  • FrançaisFrançais


  • Le code des applications écrites en C a généralement plusieurs fichiers source, mais vous devrez finalement les compiler en un seul exécutable.

    Vous pouvez le faire de deux manières : en créant un statique bibliothèque ou un dynamique bibliothèque (également appelée partagé bibliothèque). Ces deux types de bibliothèques varient en termes de création et de liaison. Votre choix dépend de votre cas d’utilisation.

    Dans un article précédent, j’ai montré comment créer un exécutable lié dynamiquement, qui est la méthode la plus couramment utilisée. Dans cet article, j’explique comment créer un exécutable lié statiquement.

    Programmation et développement

    Utiliser un éditeur de liens avec des bibliothèques statiques

    Un éditeur de liens est une commande qui combine plusieurs éléments d’un programme ensemble et réorganise l’allocation de mémoire pour eux.

    Les fonctions d’un éditeur de liens incluent :

    • Intégrer tous les éléments d’un programme
    • Trouver une nouvelle organisation de la mémoire pour que toutes les pièces s’emboîtent
    • Réactivation des adresses afin que le programme puisse s’exécuter sous la nouvelle organisation de la mémoire
    • Résolution des références symboliques

    À la suite de toutes ces fonctionnalités de l’éditeur de liens, un programme exécutable appelé un exécutable est créé.

    Les bibliothèques statiques sont créées en copiant tous les modules de bibliothèque nécessaires utilisés dans un programme dans l’image exécutable finale. L’éditeur de liens relie les bibliothèques statiques comme dernière étape du processus de compilation. Un exécutable est créé en résolvant des références externes, en combinant les routines de la bibliothèque avec le code du programme.

    Créer les fichiers objets

    Voici un exemple de bibliothèque statique, ainsi que le processus de liaison. Tout d’abord, créez le fichier d’en-tête mymath.h avec ces signatures de fonction :

    int add(int a, int b);
    int sub(int a, int b);
    int mult(int a, int b);
    int divi(int a, int b);

    Créer add.c, sub.c , mult.c et divi.c avec ces définitions de fonctions :

    // add.c
    int add(int a, int b){
    return (a+b);
    }

    //sub.c
    int sub(int a, int b){
    return (a-b);
    }

    //mult.c
    int mult(int a, int b){
    return (a*b);
    }

    //divi.c
    int divi(int a, int b){
    return (a/b);
    }

    Générez maintenant des fichiers objets add.o, sub.o, mult.oet divi.o en utilisant GCC :

    $ gcc -c add.c sub.c mult.c divi.c

    La -c L’option ignore l’étape de liaison et crée uniquement des fichiers objets.

    Créez une bibliothèque statique appelée libmymath.a, puis supprimez les fichiers objets, car ils ne sont plus nécessaires. (Notez que l’utilisation d’un trash commande est plus sûr que rm.)

    $ ar rs libmymath.a add.o sub.o mult.o divi.o
    $ trash *.o
    $ ls
    add.c  divi.c  libmymath.a  mult.c  mymath.h  sub.c

    Vous avez maintenant créé un exemple simple de bibliothèque mathématique appelée libmymath, que vous pouvez utiliser en code C. Il existe, bien sûr, des bibliothèques C très complexes, et c’est le processus que leurs développeurs utilisent pour générer le produit final que vous et moi installons pour une utilisation en code C.

    Ensuite, utilisez votre bibliothèque mathématique dans un code personnalisé, puis liez-le.

    Créer une application liée statiquement

    Supposons que vous ayez écrit une commande pour les mathématiques. Créer un fichier nommé mathDemo.c et collez-y ce code :

    #include <mymath.h>
    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
      int x, y;
      printf("Enter two numbers\n");
      scanf("%d%d",&x,&y);
     
      printf("\n%d + %d = %d", x, y, add(x, y));
      printf("\n%d - %d = %d", x, y, sub(x, y));
      printf("\n%d * %d = %d", x, y, mult(x, y));

      if(y==0){
        printf("\nDenominator is zero so can't perform division\n");
          exit(0);
      }else{
          printf("\n%d / %d = %d\n", x, y, divi(x, y));
          return 0;
      }
    }

    Notez que la première ligne est un include déclaration faisant référence, par son nom, au vôtre libmymath bibliothèque.

    Créez un fichier objet appelé mathDemo.o pour mathDemo.c:

    $ gcc -I . -c mathDemo.c

    La -I L’option indique à GCC de rechercher les fichiers d’en-tête répertoriés après. Dans ce cas, vous spécifiez le répertoire courant, représenté par un seul point (.).

    Lien mathDemo.o avec libmymath.a pour créer l’exécutable final. Il y a deux façons d’exprimer cela à GCC.

    Vous pouvez pointer vers les fichiers :

    $ gcc -static -o mathDemo mathDemo.o libmymath.a

    Vous pouvez également spécifier le chemin de la bibliothèque avec le nom de la bibliothèque :

    $ gcc -static -o mathDemo -L . mathDemo.o -lmymath

    Dans ce dernier exemple, le -lmymath indique à l’éditeur de liens de lier les fichiers objets présents dans le libmymath.a avec le fichier objet mathDemo.o pour créer l’exécutable final. La -L ordonne à l’éditeur de liens de rechercher des bibliothèques dans l’argument suivant (similaire à ce que vous feriez avec -I).

    Analyser le résultat

    Confirmez qu’il est lié statiquement à l’aide de la file commande:

    $ file mathDemo
    mathDemo: ELF 64-bit LSB executable, x86-64...
    statically linked, with debug_info, not stripped

    En utilisant le ldd commande, vous pouvez voir que l’exécutable n’est pas lié dynamiquement :

    $ ldd ./mathDemo
            not a dynamic executable

    Vous pouvez également vérifier la taille du mathDemo exécutable :

    $ du -h ./mathDemo
    932K    ./mathDemo

    Dans l’exemple de mon article précédent, l’exécutable dynamique ne prenait que 24 Ko.

    Exécutez la commande pour le voir fonctionner :

    $ ./mathDemo
    Enter two numbers
    10
    5

    10 + 5 = 15
    10 - 5 = 5
    10 * 5 = 50
    10 / 5 = 2

    Cela semble bon!

    Quand utiliser les liens statiques

    Les exécutables liés dynamiquement sont généralement préférés aux exécutables liés statiquement car la liaison dynamique maintient la modularité des composants d’une application. Si une bibliothèque reçoit une mise à jour de sécurité critique, elle peut être facilement corrigée car elle existe en dehors des applications qui l’utilisent.

    Lorsque vous utilisez une liaison statique, le code d’une bibliothèque est “caché” dans l’exécutable que vous créez, ce qui signifie que la seule façon de le corriger est de recompiler et de republier un nouvel exécutable chaque fois qu’une bibliothèque reçoit une mise à jour – et vous avez mieux choses à faire avec votre temps, croyez-moi.

    Cependant, la liaison statique est une option raisonnable si le code d’une bibliothèque existe soit dans la même base de code que l’exécutable qui l’utilise, soit dans des appareils embarqués spécialisés qui ne sont censés recevoir aucune mise à jour.

    Source

    La Rédaction

    L'équipe rédactionnnelle du site

    Pour contacter personnellement le taulier :

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

    Copy code