3 Implémentation de la bibliothèque
L'implémentation décrite ici est une implémentation possible des
bibliothèques. L'implémentation effectivement réalisée sous
Unix diffère quelque peu mais l'esprit reste le même.
3.1 la structure _iob
La bibliothèque est structurée autour d'une structure de données
regroupant toutes les informations nécessaires à la gestion des
fichiers. Cette structure est un tableau _iob
déclaré
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20
typedef struct _iobuf {
int cnt ;
char *ptr ;
char *base ;
int bufsiz ;
short flag ;
int file ;
} FILE ;
extern FILE _iob[OPEN_MAX] ;
OPEN_MAX
est le nombre maximal de fichiers pouvant être
simultanément ouverts. BUFSIZ
est la taille des buffers. Les
différents champs d'une structure _iobuf
sont :
- int cnt
- le nombre de caractères restants dans le buffer
;
- char *ptr
- est la position, dans le buffer, du prochain
caractère à traiter ;
- char *base
- est le buffer associé au fichier ;
- short flag
- est un indicateur indiquant le mode du fichier
; nous nous limiterons aux valeurs :
#define IOREAD 01
#define IOWRIT 02
#define IOEOF 020
qui indique respectivement que le fichier est ouvert en lecture,
en écriture ou que la fin de fichier a été atteinte ;
- int file
- est le descripteur autorisant l'accès au
fichier par les appels systèmes.
3.2 Fonctionnement
Lors de l'ouverture d'un flot (fopen()
), on recherche un
élément libre dans le tableau _iob
à partir du début du
tableau. Un pointeur vers cet élément sera retourné en cas de
succès. L'initialisation des différents champs est alors
réalisée2.
Les appels des fonctions bibliothèques auxquelles sont passés le
pointeur sur l'élément du tableau _iob
(FILE*
) mettent à
jour cet enregistrement et réalisent pour ce faire des appels
systèmes.
3.3 Les entrées/sorties standard
Les fichiers d'entrées et de sorties standard sont définis par
des macros :
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
et le tableau _iob
est initialisé avec
FILE _iob [OPEN_MAX] = {
{ 0, (char *) 0, (char *) 0, IOREAD, 0 },
{ 0, (char *) 0, (char *) 0, IOWRIT, 1 },
{ 0, (char *) 0, (char *) 0, IOWRIT | IOUNBUF, 2 }} ;
les deux fichiers stdout
et stderr
sont ouverts en écriture,
les écritures sur stderr
sont réalisées sans passer par un
tampon, le fichier stdin
est ouvert en lecture.
Exercice 1
Écrire les appels bibliothèques fopen()
, fclose()
,
fputc()
, fgetc()
, et ungetc()
à partir des
appels systèmes open()
, close()
, read()
, et
write()
.
Exercice 2
Quel sont les avantages de la bibliothèque sur les appels systèmes
? Pour vous persuader de ces avantages, écrire différentes
versions de la commande cat
qui recopie son entrée standard
sur sa sortie standard. Comparez les temps d'exécution (avec la
commande time
, cf. man 1 time
) d'une version «
appels systèmes » et d'une version « bibliothèque ».