1 Les appels systèmes
Les appels systèmes 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...
Nous décrivons brièvement le fonctionnement de ces primitives :
- int write (int descr, char *buf, int nbytes) ;
- La primitive
write()
réalise une écriture de nbytes
octets à partir
de l'adresse buf
dans le fichier associé au descripteur
descr
. write
retourne le nombre d'octets effectivement
écrits, -1 en cas d'erreur.
Une écriture est réalisée ainsi : si le secteur n'est pas en
mémoire, il est d'abord lu dans un des tampons systèmes (ce
qui peut obliger à libérer au préalable un tampon en le
vidant sur le disque). Puis, les octets à écrire viennent
écraser les anciens octets dans le tampon. Ce tampon sera
ensuite en mémoire jusqu'à ce qu'il doive être libéré,
auquel cas il sera écrit sur le disque.
- int read (int descr, char *buf, int nbytes) ;
- Une lecture
est réalisée par la primitive
read()
qui retourne le nombre
d'octets lus. En fin de fichier, read()
retourne donc 0.
La réalisation de la lecture charge le secteur nécessaire dans
un tampon.
Ces opérations mettant en jeu des tampons systèmes, elles
nécessitent des transferts de l'espace usager vers l'espace
système; transferts qui sont coûteux, l'espace système étant
partagé par tous les processus.
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.