Skip to topic | Skip to bottom
Home
Minfo06
Minfo06.TpAsy3r1.3 - 18 Nov 2006 - 17:52 - GuillaumeChazaraintopic end

Start of topic | Skip to actions

Rappels TP précédents

  • Faites en sorte que les images disque soient accessible à tout le monde en écriture :

ssh rl153643@madrid chmod g+w /var/tmp/centos-3.8
ssh kc152448@londres chmod g+w /var/tmp/centos-3.8
ssh po201740@rome chmod g+w /var/tmp/centos-3.8
ssh ar109855@agadez chmod g+w /var/tmp/centos-3.8
ssh fj201260@katmandou chmod g+w /var/tmp/centos-3.8
ssh oo052048@nagasaki chmod g+w /var/tmp/centos-3.8
ssh al303166@tombouctou chmod g+w /var/tmp/centos-3.8
ssh mj301307@berlin chmod g+w /var/tmp/centos-3.8
berne ?

Un périphérique caractère minimal

Cahier des charges

Écrivez un module :
  • qui implémente un pilote caractère pour un périphérique virtuel
  • qui prend en paramètres :
    • un numéro de major (mais utilise un major dynamique par défaut)
    • un message (chaîne de caractères)

Fonctionnement du périphérique virtuel :

  • Non "seekable" (plus simple)
  • Opération d'écriture :
    • Génère une trace printk à partir des données écrites
      • Programmation "paranoiaque" : vérifier la qualité et la quantité ...
  • Opération de lecture :
    • Récupération de la chaîne donnée en paramètre au module

Indications

  • Pour utiliser votre pilote vous devrez créer un fichier spécial de périphérique caractère. Vous pouvez créer ce fichier où vous voulez, mais autant le faire dans /dev, à l'aide de la commande mknod.
    • Pour créer ce fichier spécial vous devrez préciser ses numéros de major et minor. Quels sont-ils ? C'est à vous d'en décider !
      • Major : il faut choisir un numéro de major qui n'est pas déjà utilisé. Cf. indications données en cours.
      • Minor : Comme votre pilote ne gère qu'un seul périphérique virtuel, la question du minor ne pose pas, vous pouvez choisir n'importe lequel. Mais il faut quand même en choisir un, par exemple 0.
    • Attention : mknod se fiche éperdument de savoir s'il y a bien en pilote dans le noyau pour le major que vous lui donnez en paramètre. Ce n'est que lorsque vous essaierez d'utiliser le fichier spécial que le système se mettra à la recherche du pilote. Si aucun pilote n'est trouvé au moment de l'utilisation, vous obtenez un message d'erreur.
  • Lors de son chargement, votre module devra enregistrer ses services de pilote caractère auprès du système, à l'aide de la fonction register_chrdev().
    • De façon symétrique, n'oubliez pas le code qui permet de désenregistrer les services de votre pilote lors du déchargement du module. Dans le cas contraire, votre module serait "scotché" dans le noyau (impossible de le décharger).
      • Rappel : la fonction qui permet le désenregistrement est unregister_chrdev()
      • Si cette mésaventure vous arrive, vous avez deux solutions :
        • Redémarrer
        • Écrire un module qui appellera unregister_chrdev() pour vous, il faudra aussi changer le nom de votre module pour que le noyau accepte de le charger si l'ancien n'a pas pu être correctement déchargé.
  • Comment utiliser les services de votre pilote ?
    • Puisque votre pilote fournit les opérations de lecture et écriture, tout programme capable de lire et écrire dans un fichier fera l'affaire. Par exemple la commande cat pour lire le "contenu" du fichier device et les simples redirections du shell pour écrire dans le fichier device (ex echo bonjour > ficdev) .
  • Problème de la détection de la fin de fichier : Vous utilisez la commande cat et celle-ci boucle à l'infini (probablement en affichant toujours la même chose) ?
    • Vous avez simplement oublié de faire en sorte que votre pilote signale que la fin de fichier était atteinte.
      • Tant qu'elle ne voit pas d'erreur ou de fin de fichier, la commande cat pousuit ses lectures...
    • Comment signaler que la fin de fichier est atteinte ?
      C'est très simple. Comme l'indique la page de manuel de la fonction read(2), la fin de fichier est atteinte quand read renvoie 0. Et d'où vient la valeur renvoyée par la fonction read(2) ? Et bien quand le fichier lu est votre pilote de périphérique virtuel, cette valeur est celle que retourne la fonction que vous avez écrite pour implémenter l'opération de lecture. Il suffit donc de faire retourner 0 à cette fonction quand vous décidez que la fin de fichier est atteinte.
    • Hum. Grave responsabilité : comment décider que la fin de fichier est atteinte ? La fonction qui implémente l'opération de lecture est toujours suposée savoir où elle en est : elle doit savoir combien de caractères ont déjà été lus, et si tous les caractères du fichier ont déjà été lus, retourner 0 pour indiquer qu'il n'y a plus rien (et donc que la fin de fichier est atteinte).
    • Comment savoir combien de caractères ont déjà été lus ? Avant de répondre à cette question, vous devez garder à l'esprit un point de sémantique système très important : le système se souvient de ce qu'il vous a déjà retourné les fois précédentes. Autrement dit, quand vous lisez deux fois de suite dans un fichier (sans l'avoir fermé entre-temps), la seconde lecture vous retournera les caractères en partant de l'endroit où elle en était resté lors de la précédente lecture : si le fichier contient "bonjour" et que vous lisez deux fois de suite 3 caractères dans le fichier, vous obtenez "bon" la première fois, et "jou" la seconde. Puisque c'est vous qui écrivez le pilote, c'est à vous d'implémenter ce comportement.
      • Comment implémenter ce comportement ? Dans un programme normal, on se contenterait d'utiliser un variable entière déclarée statique dans le corps de la fonction pour se souvenir de la position de lecture courante. Dans le cas de notre pilote, c'est presque la même chose, si ce n'est que vous n'avez pas besoin de déclarer une variable statique, car le système a déjà prévu une variable exprès pour ça : celle qui est référencée par le troisème paramètre des fonctions implémentant les opérations de lecture et d'écriture (de type loff_t * ).
  • N'oubliez pas d'utiliser les fonctions copy_from_user et copy_to_user pour copier les données depuis l'espace mémoire du noyau vers l'espace mémoire utilisateur des processus (et vice-versa) : les pointeurs fournis en 2e paramètre des fonctions qui implémentent les opérations de lecture et d'écriture pointent vers l'espace mémoire utilisateur...
  • Tests : utilisez la commande dd pour lire ou écrire exactement le nombre d'octets souhaités (ce que ne permet pas cat )
    • Exemple : la commande dd if=ficdev bs=3 count=100 lit 100x3 caractères depuis le fichier ficdev et place le résultat sur la sortie standard.

Un compteur

Cahier des charges

L'objectif de cet exercice est de repartir du pilote précédent et de le modifier pour qu'il se comporte comme un compteur. cat ficdev devra se comporter à peu près comme seq 4000000000.

Indications

  • Une lecture n'est pas obligée de remplir totalement le buffer utilisateur
  • On supposera dans un premier lieu que le buffer de lecture est toujours suffisamment grand pour accueillir un nombre

Améliorations

  • Gérer les buffers trop petits pour accueillir un nombre "entier"
  • Implémenter l'écriture afin de pouvoir fixer la valeur initiale du compteur. Voici un exemple d'utilisation :
$ cat ficdev
0
1
2
3
....
$ echo chaine > ficdev
===> erreur
$ echo 45 > ficdev
===> OK
$ cat ficdev
45
46
47
...
  • Comparez la vitesse de votre pilote avec le voisin en utilisant la commande pv : pv ficdev > /dev/null

-- GuillaumeChazarain - 10 Oct 2006
to top


You are here: Minfo06 > TpAsy3

to top

Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WIKIDeptinfo? Send feedback