Aujourd’hui encore, un nouveau stream d’Imil … Et donc une prise de notes. Le sujet d’aujourd’hui est l’écriture de modules kernel sous Linux : On va écrire un zoli ptit driver ! Comme toujours, je ne saurais trop vous recommander de visionner directement la vidéo.
A vos compilos … prêts … partez !
Pour commencer, on va devoir installer les outils nécessaires. Sous debian et consorts, deux packages sont nécessaires :
build-essential ( Les outils habituels de dev … genre make et le compilo )
linux-headers ( qui contient les headers nécessaires pour faire un module Kernel )
Et si vous n’êtes pas sous Debian … Et bien il n’y a qu’à chercher les paquets qui vont bien ! Généralement, ce n’est pas très différent !
On commence par vérifier que tout le monde est là avec un simple ls :
Comme on peut le voir, il y a là-dedans un lien symbolique nommé “build” qui pointe vers les sources du kernel. On trouve à l’intérieur un Makefile general qui permet de compiler des modules kernel.
On y trouve également le repertoire include, avec les headers nécessaires pour compiler tout ce qui peut aller dans le kernel. Nous allons nous servir de cela dans quelques minutes !
Un tout premier module kernel
On commence par un premier module simple, qui va juste nous laisser un petit message lorsqu’il est chargé ou déchargé. Voici donc le magnifique kprout.c :
La première chose que l’on peut noter est la présence de trois includes en début de code. Ces includes nous permettent de disposer des structures, définitions et macros que nous allons utiliser pour faire notre module.
On peut également noter qu’il n’y a pas de main dans ce code. Notre module se compose en fait de fonctions que le kernel appelera. Et pour cette raison, nous allons utiliser les macros définies dans module.h pour lui indiquer lesquelles utiliser. Ainsi, cette partie du code :
module_init(prout_init);
module_exit(prout_exit);
est en fait un appel à deux macros permettant d’indiquer quelles fonctions utiliser au chargement et au déchargement du module.
Il est important de rappeler ici que nous ne pouvons pas faire appel à la libC, puisque nous sommes en ring 0 … donc pas de stdio.h et pas de printf ! A la place, nous utilisons printk, qui lui est défini dans le kernel. Il s’agit tout simplement d’un équivalent de printf, mais qui est défini dans le kernel et nous permettra d’afficher dans le dmesg.
Enfin, détail important, tout est ici déclaré en static, ce qui permet de limiter la portée de nos fonctions au fichier courant. L’objectif est tout simplement d’éviter de “polluer” le kernel avec nos fonctions, qui pourraient entrer en conflit avec des fonctions déjà définies ailleurs. Chacun chez soi ! ( J’allais dire que ça m’etonnerait de trouver “prout” dans le kernel, mais je viens de trouver prout_cmd alors je vais me taire … )
Pour compiler notre module, on va créer un fichier nommé “Kbuild” dans le même repertoire, et écrire :
obj-m = kprout.o
La ligne de compilation sera la suivante :
Et nous voilà reparti avec un make ! L’option -C nous permet d’indiquer le chemin vers le Makefile ( vous vous souvenez ? Celui dans le build dont on parlait au début ! ) et le paramètre M le chemin vers notre fichier source et notre Kbuild. Normalement, la compilation se passe plutôt bien :
Arg ! Pourquoi ça marche po ? Tout simplement parce qu’il faudrait donner quelques petites infos sur notre module : l’auteur, la licence … On utilise donc trois petites macros pour indiquer tout ça !
Et cette fois-ci …
CA Y EST ! prout.ko est notre premier module !!!!
On peut même vérifier qu’il contient les bonnes infos :
Elle est pas belle la vie ? Et en plus il fonctionne :
On peut également le décharger :
Si on veut compiler un peu plus facilement, nous pouvons ajouter à notre repertoire un Makefile tout simple :
Et voilà ! un petit make et le tour est joué !!!!
Demain, promis, je mets au propre la deuxième partie du stream !