Sommaire - API - Fonctions auxliaires

    I) Description

  1. Description du disque

    1. Les différentes zones du disque


Un disque IFS est séparé en trois zones :


      1. La zone de description

La zone de description contient au moins 3 blocs (voir plus selon le nombre de nœuds du disque).


Le super-bloc est divisé comme suit (toutes les valeurs contenues dans ce bloc sont écrites en little-endian):

Soit 128 octets en tout.


      1. La zone des nœuds

La zone des nœuds contient des informations sur les nœuds du système. Chaque bloc de cette zone contient les informations pour quatre nœuds. Chaque nœud est divisé comme suit :

      1. La zone des données

La zone des données contient des blocs qui peuvent avoir différentes structures :


    1. Gestion de la mémoire libre

Pour gérer la mémoire nous avons adopté deux stratégies distinctes pour gérer les nœuds libres et les blocs de données libres : la « carte » de noeud et la liste chaînée de blocs d'index-libre.


      1. Gestion des nœuds libres

Pour la gestion des nœuds libre, la stratégie employée est celle de la carte. Cette stratégie permet une implémentation simple de la gestion de l'espace libre tout en évitant de changer la structure de chaque bloc alloué ou libéré, cependant elle fait perdre un peu d'espace sur le disque.


Cette méthode consiste à référencer chaque noeud par un bit dans un bloc (le noeud n°0 correspond au bit n°0 du premier bloc-carte, le noeud n°1 correspond au bit n°1 du premier bloc-carte, etc...).

Pour signaler qu'un noeud est libre, le bit correspondant est positionné à 1 et pour signaler qu'un noeud est occuper, le bit correspondant est positionné à 0.

Ainsi pour trouver le premier noeud libre, il suffit de parcourir les bloc-cartes à la recherche du premier octet non nul, soit num_o son indice, puis de cherché dans cet octet l'indice du premier bit non nul, soit num_b cet indice. Si il n'y a qu'un bloc carte, on en déduit que le noeud numéro num_o × 8 + num_b est libre.


Pour éviter des recherches continuelles en cas de création ou de suppressions de nœuds, nous avons implémenté dans le super-bloc une liste de nœuds en accès rapide : à la création du disque, on la remplit avec les trente-deux premiers nœuds libres. Les demandes d'allocation ou de libération ce font par l'intermédiaire de cette liste. Si elle vient à se vider, on scanne à nouveau le bloc carte à la recherche de trente-deux nœuds libres suivants.


Cette méthode fonctionne très bien avec les nœuds qui sont relativement peu nombreux par rapports aux données. En effet, il faut tenir compte d'une perte de place relative : cette méthode utilise un bloc pour référencer 1024 nœuds, et devrait utiliser un bloc pour référencer 1024 blocs. Or bien que le système présenté est limité par l'utilisation d'un adressage sur deux octets à un disque d'environs 65 000 blocs, cela nous fera déjà perdre 64 blocs dans le pire des cas. Et dans le cas de système plus évolué, la perte d'espace serait encore plus grande. On peut donc envisager une autre technique pour la gestions des données libres.


      1. Gestion des blocs de données libres

La méthode adoptée pour gérer les blocs de données libres consiste à chaîner des index-libres. Chaque bloc d'index-libre est composé de deux octets pointant sur le bloc d'index-libre suivant, de deux octets donnant le nombre de blocs libres dans l'index et d'un tableau de soixante-deux adresses de bloc directement libre.


Fonctionnement :

Une adresse dans le super-bloc pointe sur le premier bloc libre.(a la création du disque elle est initialisée avec le denier bloc dont le champs « suivant » pointe sur l'adresse IFS_NULL).

Insertion :

Pour insérer un nouveau bloc libre dans la structure, on l'insère dans la liste de l'index-libre pointé par le super-bloc. Si cette liste est complète, alors le nouveau bloc devient un index-libre pointant sur l'ancien premier index-libre et pointé par le super-bloc.


Récupération:

Pour récupérer un bloc libre, on le retire de la liste de l'index-libre pointé par le super-bloc. Si il n'y a plus de bloc disponible dans la liste, alors l'index-libre est lui-même alloué et le super-bloc pointe sur l'index-libre suivant.


  1. Description du système

Le cœur du système est constitué d'un serveur avec lequel dialogue les fonctions de l'API(Toute opération se passe au niveau du serveur). Le serveur permet de garder en mémoire des tables et une zone de cache.


    1. Le serveur

Le choix d'un serveur pour implémenter le système demandé permet non seulement de garder en mémoires des données comme les fichiers ouverts ou les nœuds en mémoire mais aussi de fournir une meilleur simulation d'un système de fichiers. De plus, en modifiant un peu le serveur proposé qui est orienté mono utilisateur, on peut gérer avec cette méthode un système Multi-Utilisateur et introduire les systèmes distribués, où le système ne tourne pas sur la même machine que celle des utilisateurs.


Le serveur proposé est très simple :


De leur côté, les clients ont accès a une fonction send(requête) et une fonction receive (réponse) qui permettent d'envoyer et de recevoir des message sur le même principe :

send:


receive:


Pour déterminer le traitement à effectuer, la structure requête contient un code qui permet de déterminer la fonction de traitement à appeler.


    1. Les tables du système

Le système contient plusieurs tables qui permettent de garder des données en mémoires.

      1. La table des disques

La table des disques permet un accès rapides au différents disques du système. Chaque entrée de la table des disque est soit vide soit contient une structure disque qui décrit l'un des disques du système, l'indice dans cette table est le numéro attribué au disque.

L'attribution d'un numéro a un disque se fait soit lors de sa création, si il a été créé sur ce système, ou lors du lancement du système, si il a été créé sur un autre système ifs. Elle se fait par une fonction de hachage qui détermine un pré-numéro, si la case en question est déjà occupée, on lui attribue la suivante et ainsi de suite. L'utilisation de la fonction de hachage permet un accès plus rapide quand on ne connaît que le nom du disque.

La structure de disque contient toutes les informations contenues dans le super-bloc du disque plus un champs permettant de savoir si la case de la table des disques est libre ou occupée et aussi le numéro du noeud du répertoire courant pour ce disque.


      1. La table des nœuds en mémoire

La table des nœuds en mémoire conserve en mémoire principale les noeud des répertoires en train d'être parcourus ou des fichiers ouverts par la commande open.

Chaque case a une structure particulière qui en plus du noeud contient le numéro de ce noeud et le numéro du disque contenant ce noeud. De plus un champs contient un compteur de fichier ouvert qui tient le compte des fichier ouvert faisant référence à ce noeud.

La commande close ferme un fichier ouvert et décrémente la valeur du compteur de fichier ouvert. Si cette valeur devient nulle le noeud est considéré comme supprimé de la table des nœuds en mémoire.


      1. La table des fichiers ouverts

La table des fichiers ouverts conserve en mémoire des données sur les fichiers qui ont été ouverts par une commande ifs_open.

Il y a trois valeurs qui sont conservées :


L'indice de la structure de fichier ouvert dans la table est le nombre qui sert de descripteur de fichier et qui est renvoyé par la fonction ifs_open.

Un fichier peut être ouvert plusieurs fois et dans ce cas le compteur du nombre de fichier ouvert sur ce noeud est incrémenté en conséquence.


    1. Le système de caches

Afin de limiter, les accès au disque, nous avons implémenté un système de caches qui permet d’effectuer une grande partie des entrées/sorties en mémoire principale plutôt que sur le disque.

La table des caches se présente sous la forme d'un tableau dont chaque case peut contenir un blocs et les informations sur la position du bloc (numéro du disque, adresse du bloc sur le disque).


Fonctionnement en écriture :

Si je veux écrire un bloc en passant par la table des caches, il faut suivre les étapes suivantes:


Fonctionnement en lecture:

Si je veux lire un bloc en passant par la tables des caches, il faut suivre les étapes suivantes :


L’avantage de cette fonctionnalité est qu’un moins grand nombre d'accès est nécessaire sur le disque, en particulier pour des blocs utilisés plusieurs fois de suite, comme les bloc d'index lors de l'écriture d'un fichier ou les nœuds.

L'inconvénient majeur de cette technique est que le disque et la mémoire ne sont pas forcément synchronisés, il faut donc de temps en temps synchroniser le disque (soit avec une horloge qui effectue cette opération toutes les n minutes, soit après n copie, etc...). En particulier, il est nécessaire de synchroniser le disque à l'arrêt du système.

Dans la conception actuelle du système, un plantage du serveur peut entraîner la perte de la structure du disque, pour empêcher cela, on peut utiliser un système de « copy on write » pour les données sensibles comme les nœuds où l'on force l'écriture sur le disque en même temps que l'écriture dans la table des caches.



Sommaire - API - Fonctions auxliaires