3 Structure logique du système de fichiers
Le système de fichiers contient deux sortes d'entités : les
répertoires et les fichiers ordinaires. Les
répertoires permettent de structurer le système de fichiers et les
fichiers ordinaires contiennent les informations utiles. En fait, ces
deux entités sont implantées comme des fichiers avec un fonctionnement
un peu particulier pour les répertoires, le terme fichier
recouvre donc à la fois la notion de répertoire et de fichier
ordinaire.
La structuration des répertoires est purement hiérarchique. En plus
de ses sous-répertoires et de ses fichiers ordinaires, un répertoire
désigne toujours lui-même (pourquoi ?1) et son répertoire
père2.
La racine de cette hiérarchie est un répertoire particulier appelé
root qui est son propre père.
Tout fichier ordinaire est désigné au moins une fois par un ou
plusieurs répertoires3 --- sinon il est
inaccessible et ne devrait pas exister.
On appelle lien toute entrée de répertoire qui désigne un
fichier (répertoire ou ordinaire). Un répertoire contient une suite de
liens de la forme {i-nombre,nom}
. Le i-nombre est un
entier qui permet de retrouver le fichier correspondant (plus
exactement, il sert d'indice dans la table des i-noeuds) : il est
unique dans le système de fichiers. Le nom est une chaîne d'au plus
14 caractères qui identifie de façon unique une entrée du répertoire.
Un répertoire possède toujours au moins deux entrées qui sont créées
et détruites en même temps que le répertoire, ce sont
{self,"."}
qui désigne le répertoire lui-même (self est le
i-nombre du répertoire) et {pere,".."}
qui désigne le
répertoire père. Dans le cas du répertoire racine, ces deux entrées
sont fixées à {2,"."}
et {2,".."}
: le i-nombre du
répertoire racine est toujours 2. Ainsi root est son propre
père !
À l'inverse d'un fichier ordinaire, il ne peut y avoir d'autres liens
sur un répertoire que ceux créés par la structure même du système de
fichiers. En effet cela aurait pour effet de transformer
l'arborescence des fichiers en un graphe pouvant contenir des cycles
et provoquer des boucles sans fin lors de la résolution de noms de
fichiers.
Un fichier est décrit dans le système de fichiers par un unique
i-noeud qui contient les informations
suivantes4 :
-
la catégorie du fichier (ordinaire ou répertoire) ;
- le nombre de liens sur ce fichier (i.e. le nombre d'entrées
de répertoire qui désignent ce fichier) ;
- la taille (logique5) en octets du fichier ;
- un tableau des 7 premiers blocs du fichier ;
- le numéro d'un bloc de simple indirection donnant
les numéros des blocs pour les blocs suivants du fichier ;
- le numéro de bloc de double indirection qui contient lui-même
des numéros de blocs de simple indirection pour les
derniers blocs du fichier.
Ces informations sont rangées dans une structure de type
INOEUD_OCCUPE (figure 3).
/* Taille d'un bloc */
#define BLOC_SIZE 64
enum CATEGORIE {ORDINAIRE, REPERTOIRE} ;
typedef u_short NUM_BLOC
typedef struct INOEUD_OCCUPE {
enum CATEGORIE type ;
u_short liens ; /* nombre d'entrees de repertoire referencant ce inoeud */
u_long taille ; /* taille logique en octets du fichier */
#define NB_BLOCS_DIRECTS 7
NUM_BLOC direct [NB_BLOCS_DIRECTS] ; /* les 7 premiers blocs du fichier */
NUM_BLOC indirect ; /* bloc d'indirection pour les blocs suivants */
NUM_BLOC double_indirect ; /* bloc de double indirection ... */
} INOEUD_OCCUPE ;
typedef union { /* definition qui sera completee */
INOEUD_OCCUPE occupe ;
/* ... */
} INOEUD ;
/* Nombre de numeros de bloc par bloc (Pour les blocs d'indirection) */
#define NUMEROS_PAR_BLOC (BLOC_SIZE / sizeof (NUM_BLOC))
Figure 3 : Définitions de types pour les i-noeuds
Le système de fichiers contient une table des i-noeuds et c'est le
i-nombre qui sert d'indice dans cette table.
La figure 4 montre un exemple de i-noeud de
répertoire avec les blocs attachés.
Figure 4 : Un exemple de i-noeud répertoire.
On remarque que le répertoire occupe tout l'espace des blocs
utilisés (taille = 640) même si toutes les entrées ne sont
pas utilisées. Dans le cas d'un fichier ordinaire, il se
peut que le dernier bloc ne soit pas complètement utilisé.
La figure 5 montre un exemple de fichier ordinaire.
Figure 5 : Un exemple de i-noeud.
On remarque que : (1) la taille n'est pas nécessairement
multiple de celle d'un bloc (64 octets), en effet le dernier
bloc n'est pas forcément complètement utilisé ; (2) le
fichier utilise moins de blocs que ce qui semblerait
nécessaire si on regarde sa taille (i.e. il y a des trous dans le fichier), ceci est dû au fait qu'il est
possible de faire des écritures bien au-dela de la fin du
fichier. Lors de la lecture, les trous d'un tel fichier
sont considérés comme contenant des 0. Ceci peut paraître
étrange, cependant, cela facilite l'implémentation (pas de
vérification à faire lors de l'écriture) et permet de gagner
de la place lorsqu'on a d'énormes fichiers creux.
Question 1
Sachant que les blocs font BLOC_SIZE =64 octets et
qu'un numéro de bloc tient sur sizeof (NUM_BLOC) =2
octets, donnez la taille logique maximale en octets d'un fichier.
Quels sont alors les nombres totaux minimaux et maximaux de blocs
utilisés.
Question 2
Vérifiez que la taille du fichier donné dans l'exemple de
i-noeud (figure 5) n'est pas débile.
Question 3
Les blocs qui constituent un fichier sont numérotés relativement à
partir de 0. Étant donné un i-noeud et un numéro relatif de
bloc, donnez l'algorithme qui donne le numéro logique de bloc
correspondant. (En particulier, on retourne une valeur nulle pour
un bloc non effectivement alloué6.)
Question 4
Donner l'algorithme de principe de la commande du qui,
étant donné un i-noeud, retourne le nombre de blocs (ou
d'octets, option -b) effectivement utilisés par le
fichier.
Question 5
Dessinez les systèmes de fichiers en faisant figurer les
répertoires, les i-noeuds avec leurs compteurs de liens et les
fichiers dans les cas successifs suivant :
-
le système de fichiers vient d'être créé, il ne contient
que le répertoire racine ;
- on a ajouté un répertoire
usr
dans root ;
- on a ajouté un fichier
fs.c
dans le répertoire
usr
;
- on a créé, dans root, un nouveau lien de nom
xxx
sur le fichier fs.c
.
Question 6
Lorsqu'un fichier est ouvert (une ou plusieurs fois) il faut
différer une demande de destruction jusqu'à la dernière fermeture
de celui-ci, avez-vous une idée simple, mais pas forcément
judicieuse pour assurer cela ? (indication : on peut utiliser le
compteur de liens du fichier).