Et nous voici reparti pour une nouvelle vidéo d’Imil ! Aujourd’hui, nous ajoutons quelques fonctionnalités à notre module kernel prout, et surtout nous allons développer un petit programme utilisant notre driver en parallèle !
Reprenons donc le petit module de la dernière fois :
Comme expliqué précédemment, la structure file_operations (fops) joue un rôle important : elle permet d’associer des opérations (des syscalls quoi …) à des fonctions en C.
Pour l’instant, cette structure est vide. On compile tout ça et on vérifie que notre module fonctionne avant de continuer :
( Je vous laisse consulter les articles précédents pour la compilation )
Comme on peut le voir, le module se charge et se décharge correctement. On va pouvoir attaquer les choses sérieuses !
Implémentons le syscall open
Maintenant que nous disposons d’un module fonctionnel, nous allons gérer le premier des syscalls impliqués dans la lecture de notre noeud /dev/prout. Il s’agit bien sûr du syscall “open”.
Comme la dernière fois, les étapes sont simples :
écrire la fonction prout_open()
remplir la structure file_operations du module pour indiquer que le syscall open sera géré par la fonction prout_open.
Cette dernière étape est très simple, il suffit de modifier notre code ainsi :
La fonction prout_open ne peut bien entendu pas être quelconque. Elle doit respecter le prototype déclaré pour la structure file_operations, déclarée dans /usr/src/linux/include/linux/fs.h :
Ce qui nous donne :
Pour les paresseux, vous pouvez télécharger le fichier ici
Notre module est prêt : on oublie pas de recompiler et de créer le noeud /dev/prout et nous pouvons passer au client !
Ecriture du client
Le programme qui va utiliser notre driver est très simple : il ouvre le fichier /dev/prout et le referme aussitôt :
Nous compilons ce fichier (prout_client.c) et l’exécutons.
Notre fonction prout_open a bien été déclenchée par le syscall “open”.
On peut d’ailleurs le vérifier en visualisant les syscalls effectué par prout_client :
Si vous êtes perdus, pas de panique : les deux lignes qui vous intéressent parmi tout ce bazar sont celles-ci :
Tout se passe comme prévu, notre programme effectue bien deux syscalls. Le premier, “openat” est traité par notre module. Le second, “close”, n’a pas de fonction qui lui soit associée dans la structure file_operations de notre driver. Nous sommes des gens biens, c’est à dire que nous fermons bien le fichier, mais cela n’a pour l’instant aucun effet. Il est temps de corriger cela !
Implémentons maintenant le syscall pour close :
La démarche est absolument la même que précédemment. Notre code est maintenant le suivant :
Comme espéré, le syscall “close” déclenche bien également notre fonction prout_close :
Il n’y à pas grand chose à dire de cette implémentation, car elle est vraiment très similaire à celle de la fonction prout_open. On notera toutefois le nom totalement pas intuitif du champs de la structure fops : “release”. Franchement, on aurait pu imaginer plus simple …
Notre module est maintenant complet ! Félicitations !
Complément
Et si on oublie de fermer le fichier dans le client ? Est-ce grave ?
Pour s’en assurer, nous pouvons commenter la fermeture du fichier dans prout_client :
Le test montre pourtant que la fonction “prout_close” est bien toujours déclenchée :
Est-ce la libc qui rattrape le coup ? Cela serait envisagable, cependant la commande systrace ne montre pas d’appel au syscall “close” :
La fermeture du fichier est vraisemblablement faite par le kernel, lors du syscall exit_group.
Cette hypothèse est d’ailleurs renforcée par ce que nous dit la page de man dudit syscall :
Le mot de la fin
Le voyage est maintenant terminé : cet article est la fin de cette série sur l’écriture de drivers Linux. Imil nous a annoncé qu’il allait lancer un nouvel arc dans le cadre de ses streams du samedi, et il me tarde de vous les retranscrire ici.
De mon côté, je me dis cependant qu’il y a encore un petit peu de chemin à faire pour que je maitrise totalement le truc. Idéalement, j’aimerais implémenter un petit driver maison pour un gadget USB. Je vous donne donc rendez vous dans les semaines qui viennent pour jouer encore un peu dans cette voie :)