Ce cours présente les concepts fondamentaux des systèmes de fichiers, depuis les structures de données de bas niveau (inodes, blocs) jusqu’aux interfaces de programmation de haut niveau. La correspondance avec Java montre comment ces concepts universels sont implémentés dans différents langages, avec des niveaux d’abstraction variables mais des principes sous-jacents similaires.

Dans le cadre de ce cours, nous resterons focalisés sur les définitions de la famille UNIX. Certains détailles technique associé a Windows seront vaguement présenté.

Table des partitions

Une table des partitions est une structure présente au début d’un disque qui décrit la disposition des partitions sur celui-ci. Chaque partition est une portion contiguë du disque que le système d’exploitation peut formater avec un système de fichiers. La table des partitions permet au système de savoir où commence et où finit chaque partition, ainsi que son type et ses attributs. Il existe principalement deux types de tables :

  • MBR (Master Boot Record)
    • Supporte jusqu’à 4 partitions principales (ou 3 principales + 1 étendue contenant des partitions logiques).
    • La partition étendue peut contenir un nombre illimité en théorie, mais généralement jusqu’à 128 partitions logiques selon le système d’exploitation et l’outil de partitionnement.
    • Chaque entrée de partition contient le secteur de début, la taille, et le type de partition.
    • Limite de 2 To par disque, 32 bits pour les adresses de secteur.
  • GPT (GUID Partition Table)
    • Supporte un nombre quasi illimité de partitions (typiquement 128 par défaut).
    • Utilise des adresses 64 bits, donc disque jusqu’à plusieurs exaoctets (1024Po - 1 Milliard To).
    • Chaque partition possède un identifiant unique (GUID), un type et des métadonnées de redondance pour garantir la résilience.
+------------------------------------------------------------+
| Secteur 0 (MBR) ou LBA 1 (GPT Header)                      |
| - Signature disque                                         |
| - Table des partitions principale                          |
+------------------------------------------------------------+
| Entrées de partitions                                      |
| - Début / Fin en secteur                                   |
| - Type / GUID                                              |
| - Attributs (bootable, système, etc.)                      |
+------------------------------------------------------------+
| Zone réservée (GPT backup)                                 |
| - Copie de sécurité de la table des partitions             |
+------------------------------------------------------------+

La table des partitions est gérée par le noyau à travers l’abstraction du matériel.

Quelques référence pour mieux comprend les système physique sous-jacent :
- open.edu
- c-jump
- blog.stuffedcow.net

Système de fichiers

Un système de fichiers (File System) est un ensemble de mécanismes fournis par le système d’exploitation pour manipuler et stocker de l’information à travers l’abstraction du matériel proposé par le système. De cette façon, un systeme de fichier peut être instancier sur tout support. Ce dernier assure notamment :

  • l’organisation
  • la gestion des droits d’accès
  • la créeation et suppression d’informations
  • la lecture et l’écriture des données de manière structuré et transparente
  • Gestion des accès concurrents

Un système de fichiers met également en œuvre des mécanismes de redondance et de vérification de l’intégrité des informations, tels que le RAID (Redundant Array of Independent Disks) pour la duplication ou la tolérance aux pannes, ou le CRC (Cyclic Redundancy Check) et les checksums pour détecter et corriger les erreurs sur les données écrites ou lues.

Puisque la notion de système de fichiers est indépendante du support matériel, il est possible d’en instancier un directement en mémoire (RAM). De plus, un système de fichiers peut être créé à l’intérieur d’un simple fichier stocké dans un autre système de fichiers. On parle dans ce cas de filesystem in a file (exemple : images disque utilisées pour le montage ou la virtualisation).

Type de fichiers

Dans un système d’exploitation, les fichiers représentent l’unité fondamentale de stockage et d’organisation des données. Ils permettent de conserver des informations de manière persistante et se classent en différentes catégories selon leur rôle et leur mode d’accès.

graph TD A[Types de fichiers] --> B[Ordinaires] A --> C[Répertoires] A --> D[Spéciaux] B --> E[Données utilisateur] C --> F[Structure hiérarchique] D --> G[Caractères] D --> H[Blocs] G --> I[Clavier, Sockets] H --> J[Disques durs]

Fichiers ordinaires

Les fichiers ordinaires peuvent être identifiés et “typés” différemment selon le système d’exploitation :

Par leur extension (.exe, .bin, …)

  • Typiquement Windows et pas mal de logiciel “maison”
  • Exemple : .exe, .bin, .txt, .jpg
  • Les actions possibles sur un fichier sont conditionnées par cette extension
  • Avantages
    • Simple et rapide à déterminer (lecture du nom de fichier)
    • Pas besoin d’analyser le contenu du fichier
    • Cohérent pour l’association automatique avec une application.
  • Désavantage

Par leur contenu Linux Unix (cf. man file)

  • Les extensions sont indicatives mais non obligatoires
  • Le système et les outils analysent directement le contenu binaire
  • Les actions possibles sont déterminées par :
  • les droits (exécution par exemple) et
  • par le contenu (par exemple #!/bin/bash comme première ligne du fichier)
  • Avantages / Désavantage : le strict opposé

En Java :

import java.nio.file.*;

Path chemin = Paths.get("/home/user/fichier.txt");
Files.isRegularFile(chemin)
Files.isDirectory(chemin))

// Obtenir le type de contenu
String typeContenu = Files.probeContentType(chemin);

En savoir plus sur les types mime

Répertoire

  • Un répertoire peut contenir d’autres répertoires ⇒ Structure hiérarchique
  • Deux noms peuvent être associés au même inode ⇒ hard link
  • Un nom peut faire référence à un autre nom ⇒ symbolic link
  • Un répertoire peut conetnir plusieurs fichiers
graph TB A[Répertoire racine /] --> B[home] A --> C[usr] A --> D[var] B --> E[user1] B --> F[user2] E --> G[documents] E --> H[images] G --> I[fichier1.txt] G --> J[fichier2.pdf]

Équivalent Java :

import java.nio.file.*;

// Création d'un répertoire
Files.createDirectory(Paths.get("/home/user/nouveau_dossier"));

// Liste du contenu d'un répertoire
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get("/home/user"))) {
    for (Path entry : stream) {
        System.out.println(entry.getFileName());
    }
}

// Création d'un lien symbolique
Files.createSymbolicLink(
    Paths.get("/home/user/lien"), 
    Paths.get("/home/user/fichier_original.txt")
);

Fichiers spéciaux

  • Correspondent à un périphérique d’entrée-sortie
    • Adressés caractère par caractère (clavier, tubes, sockets) → character device file
    • Adressés bloc par bloc (disques) → block device file
  • Correspondent à des liens
    • un lien dur est une autre entrée de répertoire pointant vers le même inode qu’un fichier existant.
    • un lien symbolique est un fichier spécial qui contient le chemin vers un autre fichier ou répertoire (comme un raccourci).

Deux modes d’accès : séquentiel et aléatoire

Pour certains types de fichiers et matériel, il existe deux modes d’accès :

  • Séquentiel Lecture et écriture se font uniquement à partir du début.
  • Aléatoire Il est possible de déplacer un “curseur” permettant de lire et/ou d’écrire à une position “arbitraire” : Cela permet d’aller directement sur une image précise dans une vidéo sans lire la totalité des données. Et donc gagné du temps

En Java :

// Accès séquentiel avec InputStream
FileInputStream fis = new FileInputStream("fichier.txt");
int data = fis.read(); // Lecture séquentielle

// Accès aléatoire avec RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("fichier.txt", "rw");
raf.seek(100); // Positionnement à l'octet 100
int data = raf.read(); // Lecture à cette position

Virtual FS

Tous d’abors le Virtual File System (VFS) est une couche d’abstraction qui permet au noyau d’un système d’exploitation de proposer une interface uniforme, quelle que soit la variété des systèmes de fichiers réels utilisés. Au lieu de manipuler directement un type concret, les programmes utilisateurs passent via le VFS qui transmet les commandes au système de fichiers adéquat. Grâce au VFS, il devient possible de monter différents types de volumes (USB, réseau, locaux, etc.) dans une arborescence unique et transparente, sans se soucier du format réel sous-jacent. On distingue plusieurs familles selon leur usage, architecture et fonctionnalités.

graph TD A[VFS] --> B[EXT4] A --> C[NTFS] A --> D[BTRFS] A --> E[...] A --> F[memfs] A --> G[pseudofs]

Type de FS

EXT4 : C’est le système de fichiers par défaut sous Linux (voir doc), basé sur la notion de groupes de blocs qui permettent de répartir la gestion des métadonnées (inodes, bitmaps) et des données utilisateur sur tout le disque. Chaque groupe agit comme un mini-filesystem localisé, optimisant l’allocation, la réparation locale et la parallélisation du disque..

+--------------------------------------------------------------+
| Superblock (1 Ko)                                            |
| - définir la taille du volume, paramètres globaux            |
| - pointeur vers la première table de groupes                 |
+--------------------------------------------------------------+
| Groupe de blocs (typique 128 Mo)                             |
| ┌───────────────────────────────────────────────────────────┐|
| │ Superbloc (1 Ko) dans le groupe (sauvegarde)              │|
| │ Bitmap d’allocation (blocs libres/occupés)                │|
| │ Bitmap d'inodes (libres/occupés)                          │|
| │ Table d’inodes (contenus des inodes du groupe)            │|
| │ Zone de données (réservée pour fichiers et autres)        │|
| └───────────────────────────────────────────────────────────┘|
+--------------------------------------------------------------+
| Autres groupes successifs...                                 |
+--------------------------------------------------------------+

Chaque dossier (répertoire) est considéré comme un fichier spécial dont le contenu est composé d’une table listant les entrées enfants (nom, numéro d’inode, type).

  • Le répertoire référence les fichiers et sous-dossiers par leur numéro d’inode.
  • Au niveau technique, le contenu du dossier est stocké en tant qu’un fichier régulier : il contient toutes les paires (nom, @inode), ce qui permet au noyau de retrouver rapidement l’inode associé à chaque nom.
  • Ext4 optimise les gros dossiers (beaucoup de fichiers) grâce à une structure de HTree (un arbre de hachage), accélérant la recherche et la gestion même dans des dossiers ayant des milliers de fichiers.

NTFS : Le système NTFS est propriétaire et conçu par Microsoft, centré sur la Master File Table (MFT) qui contient toutes les métadonnées. Chaque fichier est représenté par un ou plusieurs enregistrements MFT, stockant attributs et données selon leur taille (résident vs non-résident). La MFT représente 12.5% du volume et chaque enregistrement occupe 1024 octets (reccord). Les petits fichier peuvent être stocker dedans, on parle alors de donné “résident”. Autrement le fichier est découpé en block de 4-64Ko et les reccords sont géré comme une list chainée contenent un pointeur vers le block.

+--------------------------------------------------------------+
| Secteur de boot (512 octets)                                 |
| - signature, paramètres globaux                              |
| - pointeur vers la Master File Table (MFT)                   |
+--------------------------------------------------------------+
| Master File Table (MFT - centrale)                           |
| ┌───────────────────────────────────────────────────────────┐|
| │ Enregistrements MFT (métadonnées de chaque fichier)       │|
| │ Attributs résidents/non résidents                         │|
| │ Pointeurs vers MFT miroir (sauvegarde)                    │|
| │ Index des clusters alloués                                │|
| └───────────────────────────────────────────────────────────┘|
+--------------------------------------------------------------+
| Zone de données utilisateur                                  |
| - Espace pour les fichiers (via clusters)                    |
+--------------------------------------------------------------+

Un dossier dans NTFS est aussi représenté par un enregistrement dédié dans la Master File Table (MFT). Le dossier est géré comme un fichier système dont l’enregistrement MFT contient l’attribut « directory index » : un index B-tree qui référence chaque nom contenu dans le dossier ainsi que le numéro d’enregistrement MFT correspondant.

Btrfs : Toutes les structures (meta, data, log, snapshot) sont stockées dans un unique B+tree permettent une recherche rapide en $O(log n)$. Chacune des structures (inode, extents, snapshot root, etc.) est dupliquée lors de modification ; garantit la consistance, isolation transactionnelle (XID), et rollback complet possible.

+--------------------------------------------------------------+
| Superbloc (64 Ko typiquement, redondé x3)                    |
| - paramètres globaux, taille volume, racine B+tree           |
+--------------------------------------------------------------+
| B+tree central                                               |
| ┌───────────────────────────────────────────────────────────┐|
| │ Nœud racine (pointe vers nœuds internes et feuilles)      │|
| │ Nœuds internes : index, mapping extents/sous-volumes      │|
| │ Feuilles : métadonnées, checksums CRC32c                  │|
| └───────────────────────────────────────────────────────────┘|
+--------------------------------------------------------------+

Un dossier sous Btrfs est une feuille ou une branche de l’arbre B+tree correspondant à un fichier-répertoire.

  • Le répertoire stocke, sous forme d’entrées dans le B+tree, la correspondance entre chaque nom et le numéro d’inode associé.
  • Le B+tree permet une organisation très rapide et flexible, même pour les répertoires massifs.
  • Comme pour ext4, chaque sous-répertoire ou fichier dans le dossier est retrouvé via son inode mais la navigation se fait par parcours du B+tree central, garantissant une performance stable quelque soit le nombre d’éléments.

ZFS : Zettabyte File System est un système de fichiers moderne et un gestionnaire de volumes combiné, conçu à l’origine par Sun Microsystems pour Solaris. Il intègre contrôle d’intégrité complet, snapshots, compression, déduplication, et gestion dynamique du stockage. Toutes les métadonnées et les données sont organisées dans des arbres de type Merkle (checksummed), permettant la détection et la correction automatique des corruptions.

+--------------------------------------------------------------+
| Pool de stockage (zpool)                                     |
| - Regroupe un ou plusieurs vdevs (disques ou RAID)          |
| - Gestion dynamique de l’espace et allocation automatique   |
+--------------------------------------------------------------+
| Arbre de métadonnées et d’objets                             |
| ┌───────────────────────────────────────────────────────────┐|
| │ Nœud racine : pointe vers tous les datasets et snapshots  │|
| │ Nœuds internes : tables d’objets, indices, mapping d’extents|
| │ Feuilles : blocs de données et métadonnées                │|
| └───────────────────────────────────────────────────────────┘|
+--------------------------------------------------------------+

Synthèse

Le choix d’un système de fichiers dépend principalement de l’OS utilisé, du type de stockage et des besoins en fiabilité. Pour un usage général sur Linux, ext4 reste le choix le plus sûr et performant : il est stable et rapide. Sur Windows, NTFS est incontournable, offrant sécurité, journaling et support natif des fonctionnalités avancées comme le chiffrement ou les quotas. Pour les environnements Linux nécessitant des fonctionnalités avancées de stockage comme les snapshots, la compression ou la tolérance aux pannes, Btrfs est adapté, notamment pour des serveurs ou des systèmes avec des volumes importants. Enfin, ZFS est recommandé pour les configurations critiques ou les NAS, grâce à sa robustesse exceptionnelle, sa protection contre la corruption, ses snapshots et sa déduplication, mais il nécessite plus de ressources et est moins universellement supporté.

Pseudo FS

Les pseudo systèmes de fichiers (ou pseudo-fs) n’offrent pas de stockage physique mais une interface virtuelle pour interagir avec le noyau ou les périphériques. Typiquement, sous Linux :

  • /proc : exposition en temps réel de l’état du système, des processus, de la configuration kernel.
  • /sys : interface pour la gestion dynamique des périphériques, modules kernel et autres tunings.
  • /dev : représente les fichiers spéciaux pour accéder aux périphériques physiques (disque, USB, carte son, etc.) via des opérations standard de lecture/écriture.

Les pseudo-fs sont ainsi essentiels pour la gestion dynamique, le monitoring et l’administration avancée du système, mais ne contiennent pas de fichiers « classiques » au sens strict.

Structure des Inodes

Un inode (index node) est la structure de données centrale des systèmes de fichiers Unix qui contient toutes les métadonnées d’un fichier ou répertoire, à l’exception de son nom. Chaque inode est identifié par un numéro unique au sein du système de fichiers et constitue l’élément fondamental permettant au noyau de gérer les fichiers de manière efficace et cohérente. Donc l’inode stocke les informations essentielles permettant de charactérisé la donné et la localiser.

classDiagram class Inode { +number: 12345 +metadata: Metadata +pointers: DataPointers } class Metadata { +UID: 1000 +GID: 1000 +permissions: "rw-r--r--" +size: 2048 +links: 1 +type: "regular file" } class DataPointers { +directPointers: array[12] +singleIndirect: pointer +doubleIndirect: pointer +tripleIndirect: pointer } class DataBlock { +data: int array[4096] } class SingleIndirectBlock { +pointers: array[1024] } class DoubleIndirectBlock { +pointers: array[1024] } class TripleIndirectBlock { +pointers: array[1024] } Inode *-- Metadata Inode *-- DataPointers DataPointers --> DataBlock DataPointers --> SingleIndirectBlock DataPointers --> DoubleIndirectBlock DataPointers --> TripleIndirectBlock SingleIndirectBlock --> DataBlock DoubleIndirectBlock --> SingleIndirectBlock TripleIndirectBlock --> DoubleIndirectBlock

Mécanisme d’addressage des données

L’inode utilise un système d’adressage hiérarchique à plusieurs niveaux pour optimiser l’accès aux données selon la taille du fichier. Cette approche permet de traiter efficacement aussi bien les petits fichiers (accès direct) que les très gros fichiers (indirections multiples). Par exemple supposons : Taille de bloc = 4 Ko, Pointeur = 4 octets, donc 1024 pointeurs par bloc d’indirection.

Niveau d’Indirection Nombre de Blocs Calcul de Capacité Capacité Maximale
Direct 12 12 × 4 Ko 48 Ko
Simple 1024 (4096/4) × 4 Ko ≈ 4 Mo
Double 1024² (4096/4)² × 4 Ko ≈ 4 Go
Triple 1024³ (4096/4)³ × 4 Ko ≈ 4 To
Fichier de 100 Ko :
┌─────────────────────────────────────────────────────┐
│ Pointeurs directs : 12 × 4Ko = 48Ko                │
│ Indirection simple : (100-48)/4 = 13 blocs         │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Table indirecte [4Ko]                           │ │
│ │ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐     │ │
│ │ │Bloc │Bloc │Bloc │Bloc │     │     │     │     │ │
│ │ │  13 │  14 │  15 │ ... │     │     │     │     │ │
│ │ └─────┴─────┴─────┴─────┴─────┴─────┴─────┘     │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

Optimisation selon l’Usage

La taille des blocs peut être configurée à la création du système de fichiers pour optimiser les performances selon l’usage prévu :

# Système avec beaucoup de petits fichiers (développement)
mkfs.ext4 -b 1024 /dev/sdb1

# Usage général (défaut recommandé)
mkfs.ext4 -b 4096 /dev/sdb1

# Serveur multimédia avec gros fichiers
mkfs.ext4 -b 8192 /dev/sdb1

Avantages et compromis :

  • Blocs petits (1Ko) : Moins de gaspillage d’espace, plus d’I/O pour les gros fichiers
    • Moins rapide car fragmentation, peu de perte
  • Blocs gros (8Ko) : Moins d’I/O pour les gros fichiers, plus de gaspillage d’espace
    • Plus rapide, plus de perte d’espace

Pour comprendre les performances des accès disque et l’impact de la taille des blocs :
- Architecture des disques durs
- Benchmarks filesystem
- Ext4 disk layout
- Linux storage stack diagram

Explication en image