Skip to topic | Skip to bottom
Home
Minfo05
Minfo05.TpAsySeance3r1.6 - 20 Oct 2005 - 09:28 - OlivierDalletopic end

Start of topic | Skip to actions

Approfondissement Système - TP3

Un périphérique caractère minimal

Cahier des charges

Ecrivez 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 un trace printk à partir des données écrites
      • Programmation "parnoiaque" : 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 charactère. Vous pouvez créer ce fichier où vous voulez (par exemple dans votre répertoire de travail), à 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, il ne vous reste plus qu'à rebooter... Ou recharger une image vmware pas trop ancienne. (Pensez à prendre des snapshots vmware de temps en temps).
  • 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.

Correction

Voici le source du module et le Makefile pour le compiler et le charger.

Une première FIFO : "mode paquet non bloquant"

Cahier des charges

L'objectif de cet exercice est de repartir du pilote précédent et de le modifier de telle façon que ce que l'on obtient lors d'une lecture du pilote soit ce que l'on a écrit lors d'une écriture précédente. Nous n'allons toutefois pas chercher pour l'instant à implémenter totalement la sémantique réelle des FIFO Unix (tubes nommés), car cela suppose notamment d'être capable de synchroniser un processus lecteur avec un lecteur écrivain (quand la FIFO est vide, le lecteur doit normalement rester bloqué jusqu'à ce qu'un écrivain y dépose des données). De plus, pour simplifier encore le problème, et en particulier la gestion du tampon, vous n'implémenterez qu'une FIFO "en mode paquet", inspirée du principe de fonctionnement des sockets en mode datagramm (UDP) :

  • chaque lecture vide complètement la FIFO, quel que soit le nombre de caractères demandés. Mais vider complètement la FIFO ne signifie en aucun retourner plus de données au processus lecteur que la quantité désirée : un processus peut récupérer moins que ce qu'il demande, jamais plus.
  • une écriture échoue si la FIFO n'est pas déjà vide. Vous rechercherez (par exemple dans la page de manuel de write(2)) le message d'erreur le plus approprié à cette situation d'erreur.

Votre FIFO devra être capable de stocker jusqu'à 2 Ko maximum.

Indications

  • Pour le stockage des données, créez un tableau de caractères de taille fixe, qui servira de tampon.
  • Vérifiez bien les quantités lues ou écrites par votre pilote :
    • Ne pas renvoyer à un processus plus de données que la quantité réellement disponible
    • Ne pas accepter de sauver dans la FIFO plus de données que la taille max du tampon

Pour la prochaine fois

A finir pour la semaine prochaine, ou simplement pour vous occuper si vous avez fini les exercices précédents avant la fin de la séance.

  1. (impératif, à rendre en binôme, par mail, à O. Dalle) Modifiez le pilote précédent pour qu'il fonctionne en "mode caractère non bloquant"
    • Tant que la FIFO n'est pas pleine, le pilote doit accepter les écritures, dans la limite du nombre de caractères encore disponibles dans le tampon
      • Tant qu'il reste un peu de place, l'écriture n'échoue pas, mais retourne la quantité qui a pu être écrite
      • Quand la FIFO est pleine, et qu'il n'est plus possible d'écrire ne serait-ce qu'un seul caractère, l'écriture échoue.
    • Tant que la FIFO n'est pas vide, le pilote doit accepter les lectures, dans la limite du nombre de caractères disponibles
      • Les données non lues restent dans la FIFO pour les lectures suivantes
      • Quand la FIFO est vide, la lecture indique une fin de fichier.
    • Le tampon doit donc impérativement être géré comme un tampon circulaire de caractères
      • Les données doivent être lue exactement dans l'ordre où elles ont été écrite (c'est une FIFO !)
      • Utilisez la commande dd pour tester tous les cas d'utilisation.
        NEW CommentairesSurLesTpRendusParLesEtudiants
  2. (optionnel) Modifiez le pilote précédent en faisant en sorte qu'il reconnaisse des commandes ioctl, comme par exemple :
    • CHARDEV_SET_STR : Changer la valeur du paramètre chaîne de caractères du module
    • CHARDEV_GET_STR : récupérer le paramètre chaîne
    • CHARDEV_GET_MAJOR : Obtenir le numéro de major utilisé par le pilote

Pour tester vos modifications, vous devrez écrire un programme C qui invoque les comandes ioctl supportées par votre pilote.

-- OlivierDalle - 05 Oct 2005
to top

I Attachment sort Action Size Date Who Comment
chardev.c manage 4.8 K 12 Oct 2005 - 21:13 OlivierDalle Source Exo1
Makefile manage 1.0 K 12 Oct 2005 - 21:13 OlivierDalle Makefile Exo1

You are here: Minfo05 > ApprofondissementSysteme > TpAsySeance3

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