Previous Up Next

2  Bibliothèque d’entrées/sorties tamporisées

Les primitives d’entrées/sorties fournies par l’interface POSIX manipulant des descripteurs de fichiers sont complétées par les fonctions de la bibliothèque C standard manipulant des structure de type FILE.

L’objet des exercices proposés ici est d’implanter, au dessus des appels systèmes POSIX, une bibliothèque utilisateur reprenant certaines des caractéristiques de la bibliothèque C.

Appels système POSIX

Les appels systèmes POSIX manipulent des descripteurs de fichiers qui sont référencés par des entiers int. Ces primitives utilisent des tampons qui ne sont pas accessibles à l’utilisateur et qui sont partagés par tous les processus. La taille de ces tampons est directement liée aux périphériques utilisés ; c’est par exemple la taille des secteurs d’un disque...

Chaque invocation d’une de ces primitives nécessite le transfert du flux d’exécution de l’espace utilisateur vers l’espace noyau ; transfert qui est coûteux.

Les entrées/sorties de ce niveau ont donc intérêt à être réalisées sur des données de taille multiple de la taille des tampons et sur une frontière multiple de cette même taille.

C’est ce type de contraintes qu’assurent les fonctions de la bibliothèque d’entrées/sorties.

Bibliothèque d’entrées/sorties standard

Les fonctions de la bibliothèque manipulent des flots (stream) implémentés par des FILE.

Le tampon associé à un flot est dans l’espace utilisateur : chaque invocation d’une opération d’entrée/sortie ne nécessite plus le passage en mode noyau. Ce dernier n’ayant lieu que pour vider ou remplir un tampon utilisateur.

La taille de ces tampons est choisie pour correspondre aux caractéristiques du périphérique. Les entrées/sorties de bas niveau se feront donc bien par taille et sur des frontières multiples de la taille des tampons systèmes.

Ces tampons système conservent cependant leur intérêt puisqu’ils permettent à un processus de ne pas attendre l’écriture réelle sur le disque et autorisent la lecture anticipée.

Outre le fait que ces entrées/sorties soient tamporisées, la bibliothèque C standard fournit aussi des fonctions de plus haut niveau qui impriment et analysent les données sous le contrôle d’une spécification de format (printf(), etc.).

Implantation d’une bibliothèque d’entrées/sorties tamporisées

On propose ici une implantation d’une version très basique d’une bibliothèque d’entrées/sorties tamporisées. Seules les équivalents des primitives fopen(), fclose(), fgetc(), et fputc() seront implantées.

On se limite aussi dans un premier temps à un mode d’accès en lecture/écriture alors la bibliothèque standard propose aussi des accès en lecture seule ou écriture seule.

La gestion d’un tampon utilisateur nécessite de mémoriser une position courante dans le tampon, l’index du tampon dans le fichier, le nombre de caractères valides dans le tampon, un indicateur signalant que le contenu du tampon a été modifié, et une référence au fichier sous la forme du descripteur associé aux appels système.


Exercice 21
 (Type de données pds_file_t)   Proposez un type de données pds_file_t, pendant du FILE de la bibliothèque standard, pour mémoriser les informations associées à un de nos flots de données.

La bibliothèque est organisée autour d’une structure de données regroupant toutes les informations nécessaires à la gestion de l’ensemble des fichiers ouverts par un processus. Le nombre de fichiers pouvant être ouverts par un processus étant borné, l’ensemble des structures associées aux flots ouverts peut être mémorisé dans un tableau.

Trois flots de données sont associées aux descripteurs STDIN_FILENO, STDOUT_FILENO, et STDERR_FILENO (0, 1 et 2) ; ils sont désignés par les symboles pds_stdin, pds_stdout, et pds_stderr qui eux-mêmes désignent les premiers éléments du tableau des références de flots.


Exercice 22
 (Table des flots et entrées/sorties standard)   Donnez la définition et initialisation du tableau des descripteurs de flots ainsi celles des symboles référençant les entrées/sorties standard.

Lors de l’ouverture d’un flot par un pds_fopen(), un emplacement libre est recherché dans le tableau des flots à partir du début du tableau. Une référence vers cet emplacement sera retournée en cas de succès. L’initialisation des différents champs de la structure est réalisée. En particulier, un appel système permet de réaliser l’ouverture du fichier associé au flot. L’allocation dynamique du tampon est réalisée, son contenu est lu depuis le fichier.


Exercice 23
 (Création et ouverture d’un flot)   Donnez la définition d’une fonction
pds_file_t *pds_fopen(const char *path); 
réalisant l’ouverture d’un flot de données et retournant une référence sur l’élément désignant ce flot dans le tableau des flots. La fonction pds_fopen() positionne le curseur de flot sur le début du flot. Si le fichier n’existe pas, pds_fopen() le crée.

Exercice 24
 (Vidage d’un tampon)   Implantez la fonction
int pds_fflush(pds_file_t *stream); 
qui vide le tampon utilisateur si nécessaire par un appel système.

Exercice 25
 (Fermeture d’un flot)   Implantez la fonction
int pds_fclose(pds_file_t *stream); 
qui termine l’utilisation d’un flot.

Exercice 26
 (Se déplacer)   Implantez la fonction
int pds_fseek(pds_file_t *stream, int position); 
qui déplace la position courante à l’octet position du flot.

Exercice 27
 (Lire un caractère)   Réalisez la fonction
int pds_fgetc(pds_file_t *stream); 
qui va chercher le prochain caractère du flot d’entrée référencé par stream et déplace l’indicateur de positionnement du flot.

Si le flot est en fin de fichier, retourne PDS_EOF. En cas d’erreur, l’indicateur d’erreur est positionné et c’est aussi cette valeur PDS_EOF qui est retournée.


Exercice 28
 (Écrire un caractère)   Donnez une implantation de la fonction
int pds_fputc(int c, pds_file_t *stream);
qui écrit le caractère c à la position courante du flot stream et incrémente cette position.

La fonction pds_fputc() retourne le caractère écrit. En cas d’erreur, la fonction retourne PDS_EOF.

Validation de la bibliothèque d’entrées/sorties tamporisées

L’implantation d’une bibliothèque comporte aussi une phase de test et validation à laquelle une durée conséquente du temps de développement doit être consacrée.

Dans un premier temps, des tests unitaires ad hoc pourront vérifier le comportement d’appels bien choisis de la bibliothèque pour en explorer toutes les fonctionnalités, y compris dans les cas limites.

Ces programmes de tests relèvent de la distribution d’une bibliothèque ; ils font aussi partie de ce qui doit être rendu en terme de travaux pratiques !

Performance d’une bibliothèque d’entrées/sorties tamporisées

Une bibliothèque d’entrées/sorties tamporisées telle que la bibliothèque standard ou celle proposée ici apporte des gains significatifs en terme de performance au prix d’une recopie supplémentaire.


Exercice 29
 (Commandes cat)   Proposez trois versions de la commande cat qui recopie sur la sortie standard les contenus des fichiers donnés en paramètre : La comparaison des performances de catbib et catsysc permet d’évaluer les avantages de la tamporisation. La comparaison des performances de catbib et catsysb permet d’évaluer le surcoût de l’allocation du tampon utilisateur et des recopies dans ce tampon utilisateur.

Par ailleurs, des comparaisons sur des fichiers de différentes tailles et des tailles de tampon variable permettent de mesurer l’influence de ces paramètres sur les performances des entrées/sorties, par exemple mesurées en megaoctets par seconde.


Previous Up Next