[kernel] Point sur les modules du noyau linux
Je vais tenter ici de faire un point sur les modules du noyau linux, leurs utilités et comment les gérer.
Définition et utilité
Rappelons tout de suite quelque base sur le noyau Linux.
Un système d’exploitation est un logiciel qui permet de lancer des applications et de faire des traitements sur une architecture matérielle. Cette architecture matérielle discute avec un programme qui est le noyau du système d’exploitation qui dialogue lui-même avec les applications lancées.
Avant l’apparition de ce système les programmes s’exécutaient directement sur le matériel et en prenaient le contrôle total. Ainsi si plusieurs applications venaient à tourner sur un même machine le moindre crash dans une application pouvait faire tomber tout la machine. La mise en place de système d’exploitation a donc été réalisé.
Un problème a très vite apparu: L’interopérabilité matérielle. Un système d’exploitation ne pouvait fonctionner que sur une architecture bien spécifique et les développements d’application pour ce système d’exploitation ne pouvaient donc pas être porté sur d’autre machine. Aujourd’hui nous retrouvons, plus ou moins, cette vision d’une machine hôte de configuration unique chez la grande marque à la pomme. Il a donc fallu trouver un moyen d’abstraire le matériel. Ainsi sont nés les modules (nous entendons ici “module” au sens d’une fonctionnalité d’un système d’exploitation tel la prise en charge d’un matériel).
Deux types de système ont vu le jour : Les noyaux monolithiques et les micros noyaux.
Dans un noyau monolithique les fonctionnalités sont directement compilées dans le noyau. Ceci à plusieurs avantages:
- L’optimisation des calculs : Les fonctionnalités étant compilées, elles sont directement accessibles par le programme.
- La prise en charge d’une plus grande gamme de matériel.
Mais cette architecture monolithique a aussi ses défauts :
- Ajouter une fonctionnalité oblige à recompiler son noyau
- Le nombre de fonctionnalité et la taille du noyau augmente de manière linéaire.
- Toutes les fonctionnalités compilées son exécuté même si nous n’en avons pas besoin.
À l’opposé des noyaux monolithiques se trouve les micros noyaux. Plus légers ils contiennent simplement un programme central qui ne contient aucune fonctionnalité hormis celle de charger d’autres fonctionnalités. Ainsi les problèmes sont inversés par rapport au noyau monolithique :
- Vous n’activer que les fonctionnalités dont vous avez besoin.
- Le point du noyau reste petit.
- Ajouter une fonctionnalité ne nécessite pas de recompiler son noyau.
A contrario les problèmes viennent de la vitesse d’exécution.
- Le programme utilise une couche supplémentaire pour accéder aux fonctionnalités.
À l’origine, Linux est un noyau monolithique (Linux ayant trouvé les micros noyaux trop lourds pour les machines de l'époque au grand damne de Andrew S. Tanenbaum. Mais aujourd’hui quelques points ont changé car Linux est devenu un noyau hybride. C’est-à-dire que vous pouvez compiler des modules dans le noyau ou en charger d’autre à la volée! Ces fonctionnalités sont disponibles depuis la version 1.2 de mars 1995.
Un module est donc une fonctionnalité qui peut être compilé ou chargé à la volée dans le noyau.
Les commandes de gestion des modules
Pour trouver des modules il existe aujourd’hui deux possibilités. La première est celle que le module recherché est compris dans le code du noyau Linux. Dans ce cas il sera compilé ou non à la compilation du noyau. La deuxième possibilité est celle du module est proposé par le constructeur (ou une communauté) via internet. Dans ce cas il vous faudra patcher votre noyau Linux et le recompiler ou compiler le module indépendamment puis le charger dans le noyau. Nous ne verrons pas ici comment compiler des modules dans le noyau ceci faisant plus l’objet d’un article sur la compilation du noyau Linux.
Les modules noyaux sont généralement stockés dans le dossier /lib/modules/<_kernel-version_>
. Où <_kernel-version_>
est le résultat de uname -r
.
Comment lister les modules activés dans le noyau ?
lsmod
Cette commande ne possède pas d’options spéciales mais est très importante, car elle nous permet de lister les modules chargés dans le noyau, nous fournit leurs tailles et surtout nous informe de leurs dépendances envers d’autre modules.
Dans l’exemple suivant nous utilisons un pipe
et un grep
pour lister tous les modules dépendant du module iwlagn (Wifi d’intel)
$ lsmod | grep iwlagn
iwlagn 60539 0
iwlcore 70142 1 iwlagn
mac80211 98639 2 iwlagn,iwlcore
cfg80211 89303 3 iwlagn,iwlcore,mac80211
firmware_class 4686 8 iwlagn,tg3,aic94xx,libsas,qla2xxx,qla1280,advansys,pcmcia
Comment avoir des informations sur un module ?
modinfo
L’utilitaire modinfo permet d’avoir des informations sur un module, qu’il soit chargé ou non. Les informations disponibles sont le nom du fichier module et son emplacement, l’auteur du module, la description du module ou encore la license du module.
Le paramètre le plus important de la commande modinfo est le nom du module dont nous souhaitons des informations. Pour cela nous pouvons procéder de deux manières :
- Écrire en dur le chemin vers le fichier module (
.o
ou.ko
). Par exemplemodinfo /lib/modules/2.6.32-gentoo-r7/misc/vmnet.ko
- Ne donner que le nom du module. Modinfo recherchera alors le module dans le dossier
/lib/modules/_<kernel-version>_
oùkernel-version
est la version du noyau actuellement en court d’exécution. Ce qui nous donne pour le même module:modinfo vmnet
Voilà ce que ceci nous remonte
# modinfo /lib/modules/2.6.32-gentoo-r7/misc/vmnet.ko
filename: /lib/modules/2.6.32-gentoo-r7/misc/vmnet.ko
supported: external
license: GPL v2
description: VMware Virtual Networking Driver.
author: VMware, Inc.
depends:
vermagic: 2.6.32-gentoo-r7 SMP mod_unload modversions 486
On retrouve plusieurs sections s’articulant suivant une logique très simple : :
Pour n’afficher qu’une information spécifique nous disposons de l’option -F qui prend en paramètre une chaîne de caractère spécifiant la ligne désirée. Par exemple pour n’avoir que la licence :
# modinfo /lib/modules/2.6.32-gentoo-r7/misc/vmnet.ko -F license
GPL v2
Des alias à cette option existent :
- -a n’affiche que l’auteur
- -d n’affiche que la description
- -l n’affiche que la licence
- -p n’affiche que les paramètres disponibles au chargement du module.
- -n n’affiche que le chemin vers le module
Comment charger ou décharger un module ?
Le chargement et le déchargement d’un module peut être réalisé de deux manières différentes : via la commande modprobe ou via les commandes insmod et rmmod. Nous verrons en parallèle ces deux méthodes.
Chargement
Le chargement d’un module s’opère via insmod ou modprobe. Via insmod nous pourrons charger un module spécifique en le spécifiant en paramètre. Par exemple :
insmod vmnet
L’utilisation de modprobe
est plus intéressante, car elle nous permet de charger un module, un groupe de modules ou encore les dépendances des modules spécifiés et ceci en une seule commande. Son utilisation est semblable car un simple modprobe /mon/module.ko suffit à charger le module et ses dépendances. Si vous souhaitez attribuer des paramètres à votre module il suffit de les spécifier après son nom comme ceci (ici nous chargeons le système de son en désactivant OSS – autrement dit nous gardons la valeur par défaut)
modprobe soundcore preclaim_oss=0
Déchargement
Le déchargement avec rmmod est aussi très simple
rmmod vmnet
Vous pouvez forcer la suppression d’un module en cours d’utilisation (même si cela n’est pas recommandé) avec l’option -f.
Avec modprobe c’est l’option -r qui permet le déchargement
modprobe -r vmnet
Comment configurer modprobe ?
Pour configurer modprobe vous pouvez soit éditer le fichier /etc/modprobe.conf s’il existe, soit éditer les fichiers à l’intérieur du dossier /etc/modprobe.d. La syntaxe de configuration est la même.
Dans ces fichiers de configuration chaque ligne correspond à une commande. Les dièses (#) sont considéré comme des commentaires et le backslash () permettent de continuer l'écriture de la ligne sur la ligne suivante.
Les commandes disponibles sont les suivantes : alias, options, install, remove, include et blacklist. Voici comment leurs rôles :
alias :Permet de faire un alias vers le module. Par exemple avec alias vmware vmnet je pourrais charger le module vmnet via modprobe vmware.
options :Permet de spécifier les options de chargement du module. Par exemple alias mymod option1=1 option2=toto chargement le mymod avec les options options1 à 1 et options2 à toto.
install :Permet d’exécuter un script à la place du chargement du module. Par exemple avec install vmware /sbin/modprobe vmnet ; /sbin/modprobe vmmon vous chargeriez les modules vmnet et vmmon avec un simple modprobe vmware. Une autre utilité de install est celle expliquée dans le man de modprobe.conf. Si nous avons un module A qui fonctionne mieux avec un module B mais qui n’est pas dépendant de B alors nous pourrions configurer modprobe comme ceci : install A /sbin/modprobe B ; /sbin/modprobe –ignore-install A. Ceci permet avec un modprobe A de charger le module B et le module A. L’option –ignore-install est utilisé pour tout de même exécuter le chargement du module A.
remove :Au même titre que install permet d’exécuter des commandes à la place du déchargement d’un module via modprobe -r
include :Inclure un fichier de configuration. Exemple include /etc/mymod/modprobe.conf
blacklist :Permet d’ignorer un module. Ceci est très utile en cas de conflit, par exemple deux modules qui accéderaient au même matériel.
Comment gérer les dépendances entre modules ?
La gestion des dépendances entre modules se passe dans le fichier /lib/modules/<_kernel-version_>/modules.dep. La syntaxe de ce fichier est la suivante :
/chemin/vers/le/modules: /chemin/vers/la/dependence1 /chemin/vers/la/dependence2 ...
Après modification du fichier vous devez exécuter depmod pour remettre en place le cache de dépendance du noyau.
# depmod
Comment charger un module au démarrage ?
Charger un module automatiquement au démarrage dépend de votre distribution.
Sous gentoo il faut éditer le fichier /etc/modules.autoload.d/kernel-2.6
pour un noyau 2.6 et ajouter le nom du module à charger sur une nouvelle ligne. Par exemple pour ajouter le module nvidia au démarrage
# echo "nvidia" >> /etc/modules.autoload.d/kernel-2.6
Sous Debian, ubuntu ou Suse il faut éditer le fichier /etc/modules et ajouter le nom du module à charger sur une nouvelle ligne. Par exemple pour ajouter le module nvidia au démarrage
# echo "nvidia" >> /etc/modules
Conclusion
Voilà nous avons fait un tour d’horizon de la gestion des modules sous Linux. Ceci pourra être complété par l’explication de la compilation des modules dans le noyau par exemple.