<-
Apache > Serveur HTTP > Documentation > Version 2.3

Support des objets dynamiques partagés (DSO)

Langues Disponibles:  en  |  fr  |  ja  |  ko  |  tr 

La conception modulaire du serveur HTTP Apache permet à l'administrateur de choisir les fonctionnalités à inclure dans le serveur en sélectionnant un certain nombre de modules. Les modules peuvent être soit intégrés statiquement dans le binaire httpd lors de la compilation du serveur, soit compilés en tant qu'objets dynamiques partagés (DSOs) qui existeront indépendamment du binaire principal httpd. Les modules DSO peuvent être compilés au moment de la construction du serveur, ou bien compilés séparément, à l'aide de l'utilitaire des extensions d'Apache (apxs), et associés au serveur ultérieurement.

Ce document décrit l'utilisation des modules DSO ainsi que les dessous de leur fonctionnement.

top

Implémentation

Le support DSO pour le chargement de modules individuels d'Apache est assuré par un module nommé mod_so qui doit être compilé statiquement dans le coeur d'Apache. Il s'agit du seul module avec le module core à ne pas pouvoir être compilé en tant que module DSO lui-même. Pratiquement tous les autres modules d'Apache distribués peuvent être compilés en tant que modules DSO en sélectionnant pour chacun d'entre eux le mode de construction DSO à l'aide de l'option --enable-module=shared du script configure, comme décrit dans la Documentation de l'installation. Une fois compilé en tant que module DSO, un module peut être chargé en mémoire au démarrage ou redémarrage du serveur à l'aide de la commande LoadModule du module mod_so, placée dans votre fichier httpd.conf.

Un nouvel utilitaire a été introduit afin de simplifier la création de fichiers DSO pour les modules d'Apache (particulièrement pour les modules tiers) ; il s'agit du programme nommé apxs (APache eXtenSion). On peut l'utiliser pour construire des modules de type DSO en dehors de l'arborescence des sources d'Apache. L'idée est simple : à l'installation d'Apache, la procédure make install du script configure installe les fichiers d'en-têtes d'Apache et positionne, pour la plateforme de compilation, les drapeaux du compilateur et de l'éditeur de liens à l'intérieur du programme apxs, qui sera utilisé pour la construction de fichiers DSO. Il est ainsi possible d'utiliser le programme apxs pour compiler ses sources de modules Apache sans avoir besoin de l'arborescence des sources de la distribution d'Apache, et sans avoir à régler les drapeaux du compilateur et de l'éditeur de liens pour le support DSO.

top

Mode d'emploi succinct

Afin que vous puissiez vous faire une idée des fonctionnalités DSO d'Apache 2.x, en voici un résumé court et concis :

  1. Construire et installer un module Apache faisant partie de la distribution, par exemple mod_foo.c, en tant que module DSO mod_foo.so :

    $ ./configure --prefix=/chemin/vers/répertoire-installation --enable-foo=shared
    $ make install

  2. Construire et installer un module Apache tiers, par exemple mod_foo.c, en tant que module DSO mod_foo.so :

    $ ./configure --add-module=type_de_module: /chemin/vers/module_tiers/mod_foo.c \
    --enable-foo=shared
    $ make install

  3. Configurer Apache pour pouvoir installer ultérieurement des modules partagés :

    $ ./configure --enable-so
    $ make install

  4. Construire et installer un module Apache tiers, par exemple mod_foo.c, en tant que module DSO mod_foo.so en dehors de l'arborescence des sources d'Apache à l'aide du programme apxs :

    $ cd /chemin/vers/module_tiers
    $ apxs -c mod_foo.c
    $ apxs -i -a -n foo mod_foo.la

Dans tous les cas, une fois le module partagé compilé, vous devez ajouter une directive LoadModule dans le fichier httpd.conf pour qu'Apache active le module.

top

Les dessous du fonctionnement des DSO

Les clônes modernes d'UNIX proposent un astucieux mécanisme communément appelé édition de liens et chargement dynamiques d' Objets Dynamiques Partagés (DSO), qui permet de construire un morceau de programme dans un format spécial pour le rendre chargeable à l'exécution dans l'espace d'adressage d'un programme exécutable.

Ce chargement peut s'effectuer de deux manières : automatiquement par un programme système appelé ld.so quand un programme exécutable est démarré, ou manuellement à partir du programme en cours d'exécution via sa propre interface système vers le chargeur Unix à l'aide des appels système dlopen()/dlsym().

Dans la première méthode, les DSO sont en général appelés bibliothèques partagées ou encore bibliothèques DSO, et possèdent des noms du style libfoo.so ou libfoo.so.1.2. Ils résident dans un répertoire système (en général /usr/lib) et le lien avec le programme exécutable est établi à la compilation en ajoutant -lfoo à la commande de l'éditeur de liens. Les références à la bibliothèque sont ainsi codées en dur dans le fichier du programme exécutable de façon à ce qu'au démarrage du programme, le chargeur Unix soit capable de localiser libfoo.so dans /usr/lib, dans des chemins codés en dur à l'aide d'options de l'éditeur de liens comme -R ou dans des chemins définis par la variable d'environnement LD_LIBRARY_PATH. Le chargeur peut dès lors résoudre tous les symboles (jusque là non encore résolus) du DSO dans le programme exécutable.

Les symboles du programme exécutable ne sont en général pas référencés par le DSO (car c'est une bibliothèque de code à usage général et réutilisable), et ainsi aucune résolution supplémentaire n'est nécessaire. De son côté, le programme exécutable ne doit accomplir aucune action particulière pour utiliser les symboles du DSO car toutes les résolutions sont effectuées par le chargeur Unix. En fait, le code permettant d'invoquer ld.so fait partie du code de démarrage pour l'exécution qui est lié dans tout programme exécutable non statiquement lié. L'avantage du chargement dynamique du code d'une bibliothèque partagée est évident : le code de la bibliothèque ne doit être stocké qu'une seule fois dans une bibliothèque système telle que libc.so, ce qui permet d'économiser de l'espace disque pour les autres programmes.

Dans la seconde méthode, les DSO sont en général appelés objets partagés ou fichiers DSO, et peuvent être nommés avec l'extension de son choix (bien que le nom conseillé soit du style foo.so). Ces fichiers résident en général dans un répertoire spécifique à un programme, et aucun lien n'est automatiquement établi avec le programme exécutable dans lequel ils sont utilisés. Le programme exécutable charge manuellement le DSO à l'exécution dans son espace d'adressage à l'aide de l'appel système dlopen(). A ce moment, aucune résolution de symboles du DSO n'est effectuée pour le programme exécutable. Par contre le chargeur Unix résoud automatiquement tout symbole du DSO (non encore résolu) faisant partie de l'ensemble de symboles exporté par le programme exécutable et ses bibliothèques DSO déjà chargées (et en particulier tous les symboles de la bibliothèque à tout faire libc.so). De cette façon, le DSO prend connaissance de l'ensemble de symboles du programme exécutable comme s'il avait été lié statiquement avec lui auparavant.

Finalement, pour tirer profit de l'API des DSO, le programme exécutable doit résoudre certains symboles du DSO à l'aide de l'appel système dlsym() pour une utilisation ultérieure dans les tables de distribution, etc... En d'autres termes, le programme exécutable doit résoudre manuellement tous les symboles dont il a besoin pour pouvoir les utiliser. Avantage d'un tel mécanisme : les modules optionnels du programme n'ont pas besoin d'être chargés (et ne gaspillent donc pas de ressources mémoire) tant qu'il ne sont pas nécessaires au programme en question. Si nécessaire, ces modules peuvent être chargés dynamiquement afin d'étendre les fonctionnalités de base du programme.

Bien que ce mécanisme DSO paraisse évident, il comporte au moins une étape difficile : la résolution des symboles depuis le programme exécutable pour le DSO lorsqu'on utilise un DSO pour étendre les fonctionnalités d'un programme (la seconde méthode). Pourquoi ? Parce que la "résolution inverse" des symboles DSO à partir du jeu de symboles du programme exécutable dépend de la conception de la bibliothèque (la bibliothèque n'a aucune information sur le programme qui l'utilise) et n'est ni standardisée ni disponible sur toutes les plateformes. En pratique, les symboles globaux du programme exécutable ne sont en général pas réexportés et donc indisponibles pour l'utilisation dans un DSO. Trouver une méthode pour forcer l'éditeur de liens à exporter tous les symboles globaux est le principal problème que l'on doit résoudre lorsqu'on utilise un DSO pour étendre les fonctionnalités d'un programme au moment de son exécution.

L'approche des bibliothèques partagées est la plus courante, parce que c'est dans cette optique que le mécanisme DSO a été conçu ; c'est cette approche qui est ainsi utilisée par pratiquement tous les types de bibliothèques que fournit le système d'exploitation. Par contre, les objets partagés sont relativement peu utilisés pour étendre les fonctionnalités d'un programme.

En 1998, seule une poignée de logiciels distribués utilisaient le mécanisme DSO pour réellement étendre leurs fonctionnalités au moment de l'exécution : Perl 5 (via son mécanisme XS et le module DynaLoader), le serveur Netscape, etc... A partir de la version 1.3, Apache rejoignit ce groupe, car Apache présentait déjà un concept modulaire pour étendre ses fonctionnalités, et utilisait en interne une approche basée sur une liste de distribution pour relier des modules externes avec les fonctionnalités de base d'Apache. Ainsi, Apache était vraiment prédestiné à l'utilisation des DSO pour charger ses modules au moment de l'exécution.

top

Avantages et inconvénients

Les fonctionnalités ci-dessus basées sur les DSO présentent les avantages suivants :

Inconvénients des DSO :

Langues Disponibles:  en  |  fr  |  ja  |  ko  |  tr