Linux & les modules 
                             -------------------
              - un tutorial avec des vrais morceaux de concret. -





NOTE: vous pouvez distribuer librement ce texte, tant que cela reste gratuit
      et que vous n'y apportez pas de modifications sans m'en avoir informé.
      Pour toutes suggestions ou corrections: jseb@hexanet.fr
      Les informations sont données à titre indicatif, et ne sauraient engager
      ma responsabilité en cas de dommages liés à une mauvaise utilisation ou
      compréhension de ce texte.






0) Brisons la glace
-------------------

Bill $ - Eh! Dis donc Tux, c'est nul de recompiler le noyau de Linux à chaque
         fois que l'on rajoute un périphérique !

Tux # - Espèce de pingouin! Tu n'as pas besoin de tout recompiler! Avec le noyau
        2.0, et ses modules magiques, tes périphériques sont fonctionnels sans
        douleur, et cela dès les basses températures!

Bill $ - Error in VXD 98. Press ctrl+alt+del to continue.






1) La traditionnelle introduction
---------------------------------

 Depuis la version 2.0 de Linux, une fonctionnalité très intéressante est 
intégrée: il s'agit des modules. Les modules correspondent à des drivers que
l'on peut charger et décharger dynamiquement de la mémoire.

 Pour les vétérans du DOS, cela correpond aux fichiers *.SYS que l'on trouvait
dans le "config.sys". Sous Dos, on ne pouvait pas les charger/décharger
dynamiquement, mais on pouvait ruser (comme pour l'ansi.sys qui ne servait pas
souvent) en utilisant des TSR (des programmes résidents qui détournaient les
interruptions pour s'exécuter régulièrement ou après un évènement).

 Sous Windows95, cela correpond aux *.VXD ou drivers de périphériques virtuels.
L'écriture d'un VXD sous Windows95 est une expérience éprouvante et plutôt
pénible, même si elle permet de faire connaissance avec le système (à noter que
les VXD sont maintenant utilisés dans l'écriture de virus, car ils permettent
de contourner complètement les mécanismes de protection et de pagination).


 Sous Linux, on utilisera les commandes LSMOD, INSMOD, RMMOD, MODPROBE et 
DEPMOD pour gérer les modules.
 Attention, si tout au long de ce texte les commandes sont en majuscule afin
de bien les souligner, il convient de les taper en minuscule.
 Puisque l'on est dans les conventions de lecture, je vous signale que j'
utilise indiféremment les termes "module" et "driver" pour désigner la même
chose (à savoir.. un résident ;) )

ATTENTION! Pour utiliser les modules, vous devez obligatoirement compiler le 
noyau avec l'option "modules" activée. Normalement, c'est le cas si vous 
utilisez le noyau fourni avec une distribution.
KERNELD doit également être présent en mémoire (ce qui doit être le cas quand
on compile avec l'option "modules").


On trouve deux avantages à compiler une fonctionnalité en module, et non 
l'intégrer dans le noyau:

a) Cela évite d'alourdir le noyau avec un tas de drivers qui ne serviront qu'
   une fois tous les 36 du mois.

b) Le driver n'est pas disponible avec les sources du noyau, et il faut le 
   rajouter un fois le noyau compilé. Dans les anciennes versions de Linux 
   (1.2.x), cela obligeait à patcher le noyau.
   Par exemple, ma carte son (une SB64 PCI de chez Creative) n'est pas   
   supportée dans les sources de mon noyau. J'ai du compiler le driver 
   séparément (voir mon autre texte qui détaille mes déboires et les solutions
   que j'ai trouvé pour me tirer d'affaire avec les SB PCI Ensoniq.)






2) Où sont les modules, quelles sont les commandes ?
----------------------------------------------------

Vous trouverez le ou les modules dans le répertoire /lib/modules/(version noyau)
Exemple, je recherche le module de ma carte son, compilé avec un noyau 2.0.36.
Je le trouve dans /lib/modules/2.0.36/misc/
Selon ce que vous avez compilé, vous trouverez d'autres noyaux et d'autres 
sous-répertoires dans votre répertoire "version noyau".
Par exemple, chez moi, le support réseau est intégré dans le noyau, mais on peut 
très bien le trouver sous forme de modules, pour les personnes chez qui il sert 
peu.

Voici une présentation des commandes qui vont vous servir.

LSMOD : liste de tous les modules présents en mémoire.

INSMOD: insérer un module en mémoire.
        (ex: " insmod /lib/modules/2.0.36/misc/snd-midi.o ")

RMMOD: enlever un module de la mémoire. (voir LSMOD)
       (ex: " rmmod snd-midi ")

DEPMOD: créer une liste des modules utilisables avec le noyau actuel.
        La liste est créée dans /lib/modules/(version noyau)/ et se nomme 
        "modules.dep" . C'est un fichier texte analogue à un fichier Makefile,
        en ce sens qu'il liste les modules disponibles, et les "sous-modules"
        (également eux-même des modules) nécessaires au bon fonctionnement de 
        ces modules. (un peu comme la liste des fichiers objets 
        nécéssaires à la compilation de l'éxecutable dans un Makefile).

MODPROBE: chargement d'un module et de toutes ses dépendances (modules qui lui 
          sont associés, voir DEPMOD).


Faites un man pour plus de précisions sur les paramètres.






3) Comment charger un module ?
------------------------------

Bien sûr, on peut tout charger à la main, à chaque fois que l'on lance Linux. 
Cela s'avère tolérable pour les essais, mais insupportable à chaque boot.
De plus, certains modules, décomposés en une kyrielle de sous-modules sont
assez pénibles à insérer (il faut se cogner tous les "insmod" à la mimine.)

Parfois, on ne sait même pas exactement ce que l'on doit charger.

Je vais prendre un exemple pratique et concret: ma fameuse SB64 PCI.

Voici les fichiers obtenus après la compilation du driver ALSA, et présents
dans /lib/modules/2.0.36/misc/


 es1371.o persist.o snd-ad1848.o snd-ac97-codec.o snd-audiodrive1688.o
 snd-audiodrive18xx.o  snd-audiopci.o snd-card-ad1848.o snd-card-cs4231.o
 snd-card-cs4232.o snd-card-cs4236.o snd-cs4231.o snd-cs4236.o snd-detect.o
 snd-emu8000.o snd-ens1370.o snd-es1688.o snd-es18xx.o snd-es1938.o
 snd-esssolo1.o snd-gus.o snd-gusclassic.o snd-gusextreme.o snd-gusmax.o
 snd-i2c.o snd-interwave-stb.o snd-interwave.o snd-midi.o snd-mixer.o
 snd-mozart.o snd-mpu401-uart.o snd-opl3.o snd-opl3sa.o snd-opti9xx.o
 snd-pcm.o snd-pcm1-oss.o snd-pcm1.o snd-s3-86c617.o snd-sb-dsp.o snd-sb16.o
 snd-sb8.o snd-sbawe.o snd-serial.o snd-sonicvibes.o snd-synth.o soundcore.o
 snd-timer.o snd-uart16550.o snd.o snd-tea6330t.o


Très bien messieurs, que dois-je charger dans tout ce fatras ? Vous avez 10 
secondes.

Bon, par élimination, on peut enlever tout ce qui contient "gus", "sb16" et
autres "sbwave". Et on charge tout le reste avec "insmod" ? Eh bien.. oui,
cela pourrait fonctionner. Mais on aurait en mémoire des tas de modules
superflus. De plus, les modules ne se chargent pas dans n'importe quel ordre.
Par exemple, ne comptez pas faire un " insmod snd-audiopci.o " sans avoir
chargé auparavant tous les sous-modules associés.

En fait, il y a bien plus simple.
Executez " depmod -a".
le paramètre "-a", c'est pour lui signaler qu'il doit scanner tous les modules
et tous les sous-répertoires.

Vous avez maintenant un fichier "modules.dep" dans "/lib/modules/2.x.x"
Vous pouvez le regarder, c'est du texte, et il contient la liste des modules
avec toutes leurs dépendances (sous-modules).

Bon, je vous mets une partie de la liste que j'ai obtenue (une partie seulement
car le fichier est assez long).


/lib/modules/2.0.36/misc/snd.o:

 -> C'est un module "stand-alone". Il n'a pas de dépendances avec les autres
    modules.



/lib/modules/2.0.36/misc/snd-timer.o: /lib/modules/2.0.36/misc/snd.o

 -> Tiens, "snd-timer.o" repose sur "snd.o".
    Pour le charger à la main, il faudrait donc faire:
    insmod snd.o
    insmod snd-timer.o



/lib/modules/2.0.36/misc/snd-ens1370.o: 
                                     /lib/modules/2.0.36/misc/snd-mixer.o
                                     /lib/modules/2.0.36/misc/snd-midi.o
                                     /lib/modules/2.0.36/misc/snd-pcm1.o
                                     /lib/modules/2.0.36/misc/snd.o
                                     /lib/modules/2.0.36/misc/snd-ac97-codec.o

 -> "snd-ens1370.o", comme son nom l'indique, correspond au module gérant le
    chip ensoniq de la SB PCI (selon les versions, c'est un ens1370 ou 1371).
    Dans les drivers ALSA, les deux chipsets sont confondus dans le même
    module.



/lib/modules/2.0.36/misc/snd-audiopci.o:/lib/modules/2.0.36/misc/snd-mixer.o
                                        /lib/modules/2.0.36/misc/snd-pcm.o
                                        /lib/modules/2.0.36/misc/snd-ens1370.o
                                        /lib/modules/2.0.36/misc/snd-midi.o
                                        /lib/modules/2.0.36/misc/snd.o

  -> Et on se rend compte que "snd-audiopci.o" est le module qui appelle tous
     les autres.
     Notez les dépendances avec des modules très généraux comme "snd-mixer",
     "snd-pcm" (qui gère les sorties vers /dev/dsp) et "snd-ens1370".



 Ce fichier généré par DEPMOD ne servira pas uniquement à satisfaire notre
 curiosité. Il est également utilisé par MODPROBE, conjointement avec un autre
 fichier, situé lui dans /etc.
 Cet autre fichier se nomme "conf.modules".
 Il contient les alias et les paramètres que l'on doit passer aux modules.
 Voici le contenu de mon "/etc/conf.modules"
      
#alias sound sb
#options -k sb io=0x220 irq=5 dma=1
#alias midi opl3
#options -k opl3 io=0x388
alias sound snd-audiopci.o

# --- BEGIN: Generated by ALSACONF, do not edit. ---
alias char-major-116 snd
alias char-major-14 snd
alias snd-card-0 snd-audiopci
alias sound-slot-0 snd-card-0
alias sound-service-0-3 snd-pcm1-oss
alias sound-service-0-12 snd-pcm1-oss
options snd snd_major=116 snd_cards_limit=1 snd_device_mode=0666
options snd-audiopci snd_index=1 snd_id=CARD_1
# --- END: Generated by ALSACONF, do not edit. ---


 Toute la partie "modules ALSA" a été générée par leur utilitaire de
configuration. J'ai simplement rajouté un alias: "sound" pour "snd-audiopci.o"
 Les lignes commentées correspondent à mon ancienne carte, et sont source de
problèmes que je détaillerai plus loin.
 Là, on voit bien l'utilité de l'alias: on a en gros toujours les mêmes choses
à charger, seul le nom des drivers change. On utilise donc des noms 
"génériques" pour pouvoir réutiliser des scripts existants. Le nom générique
étant ici "sound" pour désigner "ma superbe carte son PCI ensoniq pas
compatible SB alors que c'est une Creative et qu'elle s'appelle quand même
SoundBlaster.". Vous avouerez que c'est plus court, même si cela laisse moins
de possibilité d'extériorisation aux sentiments rancuniers.

 Il suffit donc de taper "modprobe sound", et hop, tout se retrouve en
mémoire. Un "LSMOD" nous confirme qu'il y a décidemment du monde.

 Ah oui, bien sûr, pour l'alias, il fallait évidemment savoir que le module
chapeautant la série de sous-modules est "snd-audiopci.o". Au début, j'
essayais MODPROBE avec "snd-ens1370.o", et forcément, ça ne marchait pas.

Dans un cas comme cela, il faut procéder par élimination, regarder la
façon dont les modules s'organisent dans "modules.dep" et insérer manuellement
les modules à coup de INSMOD.
Parfois, on peut même lire la doc des modules.






4) Automatisation du chargement des modules && conclusion
---------------------------------------------------------
 
 Maintenant que ça marche, il faudrait automatiser tout cela.
 Coupant court à tout suspense, je lache le morceau: tout se passe dans
"/etc/rc.init/rc.sysinit".

 D'ailleurs, j'en profite pour placer mon extrait de /etc/rc.init/rc.sysinit
Et donc... (search search) le voila..


if [ -x /sbin/depmod -a -n "$USEMODULES" ]; then
    # Get ready for kerneld if module support in the kernel
    echo -n "Finding module dependencies"
    depmod -a
    echo ""
fi

# load sound modules
if ! grep -i nomodules /proc/cmdline >/dev/null ; then
    if [ -n "$USEMODULES" ]; then
	if grep -s "alias sound" /etc/conf.modules > /dev/null ; then
	    modprobe sound

#	    if grep -s "alias midi" /etc/conf.modules > /dev/null ; then
#		modprobe midi
#provoquait une erreur, car il y a bien une chaine "midi" dans conf.modules,
#mais celle ci est en commentaire! Donc modprobe ne trouvait rien.

#ne pas oublier de commenter "fi" qui suit : le "if" en rapport est commenté.
#	    fi
	fi
    fi
fi


 Ceux qui ont lu les commentaires ont déja tout compris: dans "modules.conf",
j'avais commenté la ligne "alias midi opl3" (j'avais une soundblaster avant).
Seulement, le "rc.sysinit" greppe (tiens, un nouveau verbe) le "modules.conf"
pour voir si il n'y a pas un "alias midi". Si c'est le cas, il lance un
"modprobe midi" pour charger les modules en rapport. Ce qui se passait sur ma
config, et j'avais immanquablement un message d'erreur concernant le midi au
boot.
 J'aurais pu supprimer l'alias dans le "modules.conf", mais bon.. j'ai
modifié le premier fichier qui m'est tombé sous la main..
 Par contre, le chargement de "sound" se passe bien, d'où l'interet de
l'alias.




 Et voila.
 
 En conclusion, rappellez-vous des 3 fichier importants pour les modules:
 
 /lib/modules/2.x.x/modules.dep   (liste des dépendances,généré par DEPMOD)
 /etc/conf.modules                (alias et options des modules)
 /etc/rc.d/rc.sysinit             (chargement des modules au boot)
 
 
 
 


                                         11 juin 1999 ,
                                         Jean-Seb Lebarbier (jseb@linux-france.org)


Retour Au Menu Linux