12 février 2014

Module

Introduction

Vous avez déjà eu une présentation des modules dans le chapitre Architecture du système GNU/Linux. Refaisons le point.
Un module ou Loadable Kernel Module (LKM) en anglais est un morceau de code qui peut être chargé et déchargé dans le noyau Linux sur demande. Il apporte à ce dernier une fonctionnalité telle qu’un pilote de périphérique, un pare-feu (firewall), un protocole réseau, etc.
Les modules s’exécutent en mode kernel (anneau 0) et non dans le mode utilisateur (anneau 3).
Le fait de créer une fonctionnalité en tant que module au lieu de l’intégrer au sein du noyau évite d’alourdir celui-ci. Il n’est pas nécessaire d’inclure dans le noyau du code que l’on n’utilise pas souvent voire jamais.
Des tiers peuvent aussi développer des modules qui sont fournis à part. L’administrateur peut les installer et ensuite les charger sans qu’il soit nécessaire de recompiler le noyau.

Compiler et installer un module

Un module est compilé pour une version précise du noyau Linux.
Si, durant la mise à jour de votre système, une nouvelle version du noyau est installée alors tous les modules fournis par la distribution seront compilés de nouveau. Par contre, les modules que vous avez ajoutés personnellement ne seront pas recompilés. Vous devrez les recompiler manuellement.

1. Pré-requis pour compiler

La compilation nécessite un ensemble d’outils tel que le compilateur gcc (The GNU Compiler Collection), l’utilitaire make...

a. Debian et Ubuntu

Vous devez installer les paquets gcc, build-essential et les fichiers d’en-têtes (headers) du noyau :
# apt-get install gcc build-essential linux-headers-$(uname -r)

b. Red Hat

Installez les outils de développement :
# yum groupinstall "Development tools"

2. Écrire un module « Hello world »

Pour comprendre la mise en place d’un LKM, vous allez concevoir en langage C un module simple et traditionnel dans le monde du développement : « hello world ».
Le but de ce dernier est d’envoyer un message dans le journal système /var/log/syslog pendant son chargement ou son déchargement.

a. Rédiger le code source

À l’aide d’un éditeur de texte tel que vi ou nano, créez le fichier hello.c :
#include <linux/module.h>         
#include <linux/kernel.h>         
 
MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("John Doe"); 
MODULE_DESCRIPTION("Module hello world"); 
MODULE_VERSION("Version 1.00"); 
 
int init_module(void) 
{ 
      printk(KERN_INFO "[Hello world] - La fonction init_module()  
est appelée.\n"); 
      return 0; 
} 
 
void cleanup_module(void) 
{ 
      printk(KERN_INFO "[Hello world] - La fonction  
cleanup_module() est appelée.\n"); 
}
Les deux premières lignes du code source incluent deux fichiers d’en-têtes :
  • module.h nécessaire pour tous les modules,
  • kernel.h pour la définition des macros comme KERN_INFO.
Les macros MODULE_LICENSE, MODULE_AUTHOR, MODULE_DESCRIPTION et MODULE_VERSION définissent des informations sur le module.
int init_module(void) et void cleanup_module(void) sont deux fonctions nécessaires puisque la première s’exécute lors du chargement et la seconde pendant le déchargement du module.
La fonction printk() affiche les messages dans le journal du noyau. Du fait que nous sommes dans un bas niveau (espace noyau), nous ne pouvons pas utiliser la fonction printf() définie dans le fichier stdio.h qui affiche une chaîne de caractères à l’écran. Cette dernière est utilisable dans l’espace utilisateur.

b. Créer le fichier Makefile

Le fichier Makefile contient les instructions utilisées par make pendant la construction d’un exécutable, d’une bibliothèque ou bien d’un module.
Tapez les lignes suivantes dans un éditeur de texte et enregistrez le fichier sous le nom de Makefile :
obj-m += hello.o 
 
all: 
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD)  
modules 
 
clean: 
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 
 
install: 
      cp ./hello.ko /lib/modules/$(shell uname  
-r)/kernel/drivers/misc
obj-m (object module) signifie qu’il existe un objet nommé hello.o qui sera construit à partir de hello.c.
Ensuite, Makefile contient trois cibles :
  • all:
  • clean:
  • install:
La cible all: construit le module. Si vous tapez uniquement make, la première cible du fichier Makefile sera appliquée en l’occurrence all:. C’est identique à make all.
La cible clean: nettoie les fichiers de construction d’une précédente compilation. Par exemple, si une compilation effectuée avec make se termine par un échec. Vous corrigez les erreurs rencontrées. Avant de relancer la commande make, vous devez nettoyer les fichiers de la précédente compilation en invoquant make clean.
Si vous exécutez make install, la cible install: installe l’exécutable dans les répertoires spécifiés.

c. Compiler le code source hello.c

Tapez make pour construire le module :
# make 
make -C /lib/modules/2.6.32-5-amd64/build M=/home/bob modules 
make[1]: entrant dans le répertoire «/usr/src/linux-headers- 
2.6.32-5-amd64» 
  CC [M]  /home/bob/hello.o 
  Building modules, stage 2. 
  MODPOST 1 modules 
  CC      /home/bob/hello.mod.o 
  LD [M]  /home/bob/hello.ko 
make[1]: quittant le répertoire « /usr/src/linux-headers-2.6.32-5- 
amd64 »
La construction a créé plusieurs fichiers car celle-ci se réalise en différentes étapes. Le fichier module proprement dit est hello.ko :
# ls 
hello.c   hello.mod.c  hello.o  Makefile  modules.order  hello.ko 
hello.mod.o  Module.symvers

Obtenir des informations

Modinfo affiche les informations d’un module telles que le nom du fichier et son emplacement, sa licence, une description, le ou les auteurs, les dépendances et sa version.
Syntaxe
modinfo <nom_du_module>
Les informations du module ext3
# modinfo ext3 
filename:       /lib/modules/2.6.32-5-amd64/kernel/fs/ext3/ext3.ko 
license:        GPL 
description:    Second Extended Filesystem with journaling extensions 
author:         Remy Card, Stephen Tweedie, Andrew Morton, Andreas  
Dilger, Theodore Ts’o 
and others 
depends:        mbcache,jbd 
vermagic:       2.6.32-5-amd64 SMP mod_unload modversions
Les dépendances peuvent être affichées également avec modprobe.
Syntaxe
modprobe <option> <nom_du_module>
Option :
Option longue
Description
--show-depends
Liste les dépendances d’un module.
Exemple
# modprobe --show-depends ext4  
insmod /lib/modules/3.10.2-20130726/kernel/fs/mbcache.ko 
insmod /lib/modules/3.10.2-20130726/kernel/fs/jbd2/jbd2.ko  
insmod /lib/modules/3.10.2-20130726/kernel/lib/crc16.ko 
insmod /lib/modules/3.10.2-20130726/kernel/fs/ext4/ext4.ko
ou encore avec lsmod :
# lsmod |grep ext4  
ext4                  377227  3  
crc16                  12343  2 ext4,bluetooth  
mbcache                13082  1 ext4  
jbd2                   76198  1 ext4 
Vous pouvez organiser l’affichage des informations des modules : nom du module et emplacement, description et dépendances en utilisant des commandes avancées du shell. Par exemple :
  • cut affiche des zones spécifiques d’un fichier texte. -d définit le séparateur de champ et -f1 extrait le premier champ.
  • sed (Stream Editor) permet de manipuler du texte.
  • egrep (ou grep -E) affiche les lignes correspondant à un motif.
  • Les expressions rationnelles et les expressions rationnelles étendues...
Premier exemple
# modinfo $(cut -d’ ’ -f1 /proc/modules) | sed ’/ˆdep/s/$/\n/;  
/ˆfile\|ˆdesc\|ˆdep/!d’ 
 
filename: /lib/modules/2.6.32-5-amd64/kernel/drivers/misc/hello.ko 
description: Un exemple de LKM 
depends: 
 
filename: /lib/modules/2.6.32-5-amd64/kernel/drivers/cpufreq/ 
cpufreq_powersave.ko 
description: CPUfreq policy governor ’powersave’ 
depends: 
                               ... 
filename: /lib/modules/2.6.32-5-amd64/kernel/fs/ext3/ext3.ko 
description: Second Extended Filesystem with journaling extensions 
depends: mbcache,jbd 
 
filename: /lib/modules/2.6.32-5-amd64/kernel/fs/jbd/jbd.ko 
depends: 
 
filename: /lib/modules/2.6.32-5-amd64/kernel/fs/mbcache.ko 
description: Meta block cache (for extended attributes) 
depends: 
                               ...
Deuxième exemple
# lsmod | cut -d’ ’ -f1 | xargs modinfo | egrep ’ˆfile|ˆdesc|ˆdep’  
| sed -e’/ˆdep/s/$/\n/g’  
filename: /lib/modules/2.6.32-5-amd64/kernel/drivers/misc/hello.ko 
description: Un exemple de LKM  
depends: 
 
filename: /lib/modules/2.6.32-5-amd64/kernel/drivers/cpufreq/ 
cpufreq_powersave.ko  
description: CPUfreq policy governor ’powersave’  
depends: 
                               ...
Troisième exemple
# find /lib/modules/$(uname -r) -name ’*.ko’ | xargs modinfo  
filename:       /lib/modules/3.10.2- 
20130726/kernel/net/bluetooth/rfcomm/rfcomm.ko  
alias:          bt-proto-3  
license:        GPL  
version:        1.11  
description:    Bluetooth RFCOMM ver 1.11  
author:         Marcel Holtmann <marcel@holtmann.org>  
srcversion:     7D57E08D7FBF2D6B1E7BFA7  
depends:        bluetooth  
intree:         Y  
vermagic:       3.10.2-20130726 SMP mod_unload modversions  
parm:           disable_cfc:Disable credit based flow control  
(bool)  
parm:           channel_mtu:Default MTU for the RFCOMM channel  
(int)  
parm:           l2cap_mtu:Default MTU for the L2CAP connection  
(uint)  
parm:           l2cap_ertm:Use L2CAP ERTM mode for connection  
(bool)  
filename:       /lib/modules/3.10.2- 
20130726/kernel/net/bluetooth/cmtp/cmtp.ko  
alias:          bt-proto-5  
license:        GPL  
version:        1.0  
description:    Bluetooth CMTP ver 1.0  
author:         Marcel Holtmann <marcel@holtmann.org>  
srcversion:     8369758E5A8D8842F5E5A94  
depends:        kernelcapi,bluetooth  
intree:         Y  
vermagic:       3.10.2-20130726 SMP mod_unload modversions  
 
                               ... 
 
filename:       /lib/modules/3.10.2- 
20130726/kernel/sound/synth/snd-util-mem.ko  
license:        GPL  
description:    Generic memory management routines for soundcard  
memory allocation  
author:         Takashi Iwai  
depends:         
intree:         Y  
vermagic:       3.10.2-20130726 SMP mod_unload modversions 

Aucun commentaire :

Enregistrer un commentaire