![]() |
M2 SETI B4 / MS SE SE758 |
L’objectif de ce TP est de compiler et charger votre premier module noyau.
Nous allons reprendre le répertoire créé lors du précédent TP.
$ export TPROOT=xxx
$ cd $TPROOT
Pensez à adapter les commandes ci-dessus en fonction du nom donné au
répertoire lors du premier TP (remplaçez xxx
par
/home/users/xxx/seti-b4-tp
par exemple si vous êtes sur les
machines de l’école).
Par rapport aux deux TP précédents, vous devez conserver :
arm-linux-gnueabihf
de Linaro
que vous aviez téléchargée lors du premier TP.Profitez-en pour vérifier qu’elle est toujours dans votre
PATH
en tapant :
$ arm-linux-gnueabihf-gcc --version
Vérifiez que le résultat de cette commande est :
arm-linux-gnueabihf-gcc (Linaro GCC 7.4-2019.02) 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4]
qemu
que vous aviez téléchargée
lors du premier TP.Vous pouvez supprimer le reste afin de libérer de la place si besoin.
Pour ce TP, ainsi que les suivants, vous aurez besoin de récupérer :
Déplacez ces trois composants dans votre répertoire
$TPROOT
et décompressez l’archive contenant le noyau :
$ tar xJf linux_build.tar.xz
Vous pouvez supprimer l’archive une fois décompressée afin de gagner de la place :
$ rm linux_build.tar.xz
Vérifiez que le noyau et l’image fournie démarrent correctement :
$ cd $TPROOT
$ ./qemu-system-arm -nographic -machine vexpress-a9 -kernel linux-5.10.19/build/arch/arm/boot/zImage \
-initrd rootfs.cpio.gz -dtb linux-5.10.19/build/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
Vous devriez voir sur la console le démarrage de Linux puis un écran
de login. Vous pouvez vous connecter en tant que root
(sans
mot de passe).
Rappel : pour quitter QEMU, faites ctrl-a c
, puis
quit
.
Voici le code de votre premier module.
/* first.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init first_init(void)
{
("Hello world!\n");
pr_inforeturn 0;
}
static void __exit first_exit(void)
{
("Bye\n");
pr_info}
(first_init);
module_init(first_exit);
module_exit
("GPL");
MODULE_LICENSE("My first module");
MODULE_DESCRIPTION("Me"); MODULE_AUTHOR
Ce module ne fait pas grand chose, à l’exception d’afficher un message lors de son chargement et un autre lors de son déchargement.
Voici le fichier Makefile
nécessaire pour compiler le
module :
ifneq ($(KERNELRELEASE),)
# kbuild part of makefile
obj-m := first.o
else
# normal makefile
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
endif
Attention ! La ligne $(MAKE) -C...
qui
indique la commande à exécuter pour construire la cible
default
doit être indentée à l’aide d’une tabulation et non
d’un ou plusieurs espaces.
Ce Makefile
est très bien adapté à la compilation d’un
module depuis la machine sur lequel vous voulez l’utiliser (compilation
native). Nous verrons par la suite comment l’utiliser dans le contexte
de la compilation croisée (cross-compilation).
Plusieurs outils vous permettent de manipuler les modules :
modinfo <nom_module|module.ko>
permet d’obtenir
les informations sur un module (auteur, description, licence
d’utilisation, version du noyau pour laquelle il a été compilé, liste
des paramètres acceptés, etc.)insmod <module.ko>
permet de charger un
modulemodprobe <nom_module>
permet de charger un module
et ses dépendances éventuelleslsmod
permet de lister les modules actuellement
chargésrmmod <nom_module>
permet de décharger un module.
Cette opération n’est possible que si le module n’est pas en cours
d’utilisationmodprobe -r <nom_module>
permet également de
décharger un module et toutes ses dépendances si elles ne sont pas
utiliséesCréez un répertoire de travail pour votre premier module :
$ cd $TPROOT
$ mkdir premier_module
$ cd premier_module
Copiez le module ci-dessus ainsi que le
Makefile
Compilez votre module
$ make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm KDIR=../linux-5.10.19/build/
La variable CROSS_COMPILE
indique le préfixe des outils
de la chaîne de compilation que nous utilisons (donc le gcc
qui sera appelé est arm-linux-gnueabihf-gcc
). La variable
ARCH
indique que nous compilons pour l’architecture
arm
. Enfin KDIR
pointe vers le répertoire dans
lequel le noyau a été compilé (en effet, bien que vous compilez le code
de votre module à l’extérieur de l’arbre des sources du noyau, le
mécanisme de compilation a besoin notamment des fichiers d’entêtes du
noyau).
Votre module est maintenant dans le fichier
first.ko
.
Démarrez QEMU :
$ cd ..
$ ./qemu-system-arm -nographic -machine vexpress-a9 -kernel linux-5.10.19/build/arch/arm/boot/zImage \
-initrd rootfs.cpio.gz \
-dtb linux-5.10.19/build/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -device virtio-9p-device,fsdev=mnt,mount_tag=mnt -fsdev local,path=premier_module,security_model=mapped,id=mnt
Voici quelques explications sur les différents arguments passés à QEMU :
-machine vexpress-a9
: indique le type de machine à
simuler (ici une carte Arm Versatile Express munie d’une carte
d’extension CoreTile Express A9x4)-kernel linux-5.10.19/build/arch/arm/boot/zImage
:
indique l’image du noyau Linux à charger au démarrage-dtb linux-5.10.19/build/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
: indique le fichier contenant l’arbre des périphériques à charger au
démarrage-initrd rootfs.cpio.gz
: indique l’image du système de
fichiers racine à charger en mémoire (ici une image
initramfs
)-fsdev local,path=premier_module,security_model=mapped,id=mnt -device virtio-9p-device,fsdev=mnt,mount_tag=mnt
permet de partager le contenu du répertoire premier_module
entre votre machine et la machine émulée par QEMUAprès vous être loggué en tant que root
, montez le
partage avec la machine hôte en tapant, dans la console émulée par QEMU
:
$ mount -t 9p -o trans=virtio mnt /mnt -oversion=9p2000.L,msize=10240
Si cette commande s’exécute correctement, vous aurez alors accès,
dans le répertoire /mnt
de la machine émulée par QEMU, au
contenu du répertoire premier_module
de votre machine (et
donc au module que vous venez de compiler).
Chargez votre module (depuis QEMU) :
$ insmod /mnt/first.ko
Déchargez votre module
$ rmmod first
Félicitations, vous avez écrit votre premier module pour le noyau.
© Copyright 2020 Guillaume Duc. Le contenu de cette page est mis à disposition selon les termes de la Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International (à l'exception des exemples de code tirés du noyau Linux et qui sont distribués sous leurs licences d'origine).