Appels système du Système de Gestion de Fichier
Les appels système d'entrées-sorties ou entrées-sorties de bas niveau sont rudimentaires mais polymorphes, en effet c'est eux qui permettent d'écrire des programmes indépendamment des supports physiques sur lesquels se font les entrées/sorties et de pouvoir facilement changer les supports physiques associés a une entrée-sortie. Les appels système du système de gestion de fichier sont :
- open/creat ouverture/création d'un fichier
- read/write lecture/écriture sur un fichier ouvert
- lseek déplacement du pointeur de fichier
- dup,dup2 copie d'ouverture de fichier
- close fermeture d'un fichier
- mount changement d'un disque
- mknode création d'un inode de fichier spécial
- pipe création d'un tube
- fcntl manipulation des caractéristiques des ouvertures de fichiers
Les appels système sont réalisés par le noyau et retournent -1 en cas d'erreur.
open
#include <fcntl.h>
int open(char *ref, int mode, int perm);
Ouverture du fichier de référence (absolue ou relative à "."). Le mode d'ouverture est une conjonction des masques suivants :
O_RDONLY
O_WRONLY
O_RDWR
O_NDELAY
O_APPEND
O_CREAT
O_TRUNC
O_EXCL
La paramètre permission n'a de sens qu'à la création du fichier, il permet de
positionner les valeurs du champ mode
de l'inode. Les droits effectivement
positionnés dépendant de la valeur umask, grâce à la formule droit = perm & ~ umask
. La valeur par défaut de umask est 066. La valeur de retour de open
est
le numéro dans la table de descripteur du processus qui a été utilisé par
open
. Ce numéro est appelé descripteur de l'ouverture. Ce descripteur est
utilisé dans les autres appels système pour spécifier l'ouverture de fichier sur
laquelle on veut travailler et -1 en cas d'échec de l'ouverture.
Déroulement interne d'un appel de open
- Le système détermine l'inode du fichier référence
- Soit l'inode est dans la table des inodes en mémoire. Soit il alloue une entrée et recopie l'inode du disque.
- Le système vérifie les droits d'accès dans le mode demandé.
- Il alloue une entrée dans la table des fichiers ouverts du système, et
positionne le curseur de lecture écriture dans le fichier (offset = 0, sauf
dans le cas du mode
O_APPEND
offset= taille du fichier). - Le système alloue une place dans la table des descripteurs
_iob
du fichier. - Il renvoie au processus le numéro de descripteur, c'est à dire le numéro de
l'entrée qu'il vient d'allouer dans le table
_iob
.
Si l'opération a échoué dans une des étapes le systèmé renvoie -1.
creat
Création d'un fichier et ouverture en écriture int creat(char* reference, int permissions);
. Le système détermine l'inode du catalogue où l'on demande la
création du fichier.
- Si il existe déjà une inode pour le fichier
- Le noyau lit l'inode en question (allocation dans la table des inodes en mémoire), vérifie que c'est une fichier ordinaire autorisé en écriture par les propriétaire effectif du processus, sinon échec.
- Le système libère les blocs de données et réduit la taille du fichier à zéro, il ne modifie pas les droits qu'avait le fichier antérieurement
- Si n'existait pas d'inode pour le fichier
- Le système teste les droit en écriture sur le catalogue
- Il alloue une nouvelle inode
- Il alloue une nouvelle entrée dans la table des inodes en mémoire
read
int nbcharlus = read(int d, char* tampon, int nbalire)
- descripteur entrée de la table des descripteurs correspondante au fichier
dans lequel doit être effectuée la lecture (fourni par
open
) - nbalire nombre de caractère à lire dans le fichier
- tampon un tableau de caractères alloué par l'utilisateur. Les caractères lus sont placés dans ce tampon
- nbcharlus nombre de caractères effectivement lus, ou -1 en cas d'échec de l'appel système, la fin de fichier est atteinte quand le nombre de caractères lus est inférieur au nombre de caractères demand és.
Déroulement :
- Vérification du descripteur -> accès aux tables système
- Droits (mode adéquat)
- Grâce à l'inode le système obtient les adresses du bloc contenant les données à lire. Le système effectue la lecture de ces blocs
- Le système recopie les données du buffer cache vers le tampon de l'utilisateur
- Le curseur dans le fichier est remit à jour dans l'entrée de la table des fichiers ouverts
- Le système renvoie le nombre de caractères effectivement lus
write
int nbcecrits = write(int desc, char* tampon, int nbaecrire);
Même déroulement
que read
mais avec une allocation éventuelle de bloc-disque dans le cas d'un
ajout au-delà de la fin du fihcier. Dans le cas où l'appel concerne une
périphérique en mode caractère : le système active la fonction write
(réciproquement read
pour une lecture) du périphérique qui utilise directement
l'adresse du tampon utilisateur.
Remarquons ici encore le polymorphisme de ces deux appels système qui permet de
lire et d'écrire sur une grande variété de périphériques en utilisant une seule
syntaxe. Le code C utilisant l'appel système marchera donc indifféremment sur
tous les types de périphériques qui sont définis dans le système de fichier. Par
exemple, il existe deux périphériques "logiques" qui sont /dev/null
et
/dev/zero
(que l'on ne trouve pas sur toutes les machines). Le premier est
toujours vide en lecture et les écritures n'ont aucun effet (il est donc
possible de déverser n'importe quoi sur ce périphérique). Le deuxième fournit en
lecture une infinité de zéro et n'accepte pas l'écriture.
lseek
off_t lseek(int d, off_t offset, int direction)
lseek
permet de déplacer le
curseur de fichier dans la table des fichiers ouverts du système, offset est
un déplacement en octets, d est le descripteur et direction une des trois macros
L_SET, L_INCR, L_XTND
.
L_SET
la nouvelle position est offset sauf si offset est supérieur à la taille du fichier, auquel cas la position est égale à la taille du fichier. Si l'offset est négatif, alors la position est zéro.L_INCR
la position courante est incrémentée deoffset
placeL_XTND
déplacement par rapport à la fin du fichier, cette option permet d'augmenter la taille du fichier
La valeur de retour de lseek
est la nouvelle position du curseur dans le
fichier ou -1 si l'appel a échoué.
dup
et dup2
Les appls dup
et dup2
permettent de dupliquer des entrées de la table des
descripteurs du processus. int descripteur2 = dup(int descripteur1);
- vérification que descripteur est le numéro d'une entrée non nulle
- recopie dans la première entrée libre du table des descriptuers l'entrée correspondant à descripteur1.
- le compteur de descripteurs de l'entrée associée à descripteur1 dans la table des ouvertures de fichiers est incrémenté
- renvoi de l'indice dans la table des descripteurs de l'entrée nouvellement allouée.
close
Fermeture d'un fichier int ok = close(descripteur);
- si descripteur n'est pas un descripteur valide retour -1
- l'entrée d'indice descripteur de la table est libérée
- le compteur de l'entrée de la table des fichiers ouvert associé à descripteur est décrémenté.