Skip to main content

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

  1. Le système détermine l'inode du fichier référence
  2. Soit l'inode est dans la table des inodes en mémoire. Soit il alloue une entrée et recopie l'inode du disque.
  3. Le système vérifie les droits d'accès dans le mode demandé.
  4. 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).
  5. Le système alloue une place dans la table des descripteurs _iob du fichier.
  6. 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 :

  1. Vérification du descripteur -> accès aux tables système
  2. Droits (mode adéquat)
  3. 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
  4. Le système recopie les données du buffer cache vers le tampon de l'utilisateur
  5. Le curseur dans le fichier est remit à jour dans l'entrée de la table des fichiers ouverts
  6. 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 de offset place
  • L_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);

  1. vérification que descripteur est le numéro d'une entrée non nulle
  2. recopie dans la première entrée libre du table des descriptuers l'entrée correspondant à descripteur1.
  3. le compteur de descripteurs de l'entrée associée à descripteur1 dans la table des ouvertures de fichiers est incrémenté
  4. 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);

  1. si descripteur n'est pas un descripteur valide retour -1
  2. l'entrée d'indice descripteur de la table est libérée
  3. le compteur de l'entrée de la table des fichiers ouvert associé à descripteur est décrémenté.