Au fil des quatre premiers volets, nous avons suivi comment une requête d’E/S s’écoule (parties 1 à 3) et comment le gestionnaire de cache la reçoit (partie 4). Au bout du compte, la requête arrive au système de fichiers. Cette fois, c’est le tour de son représentant le plus connu, NTFS.
Le point de vue change ici. Jusqu’à présent, l’histoire était dynamique — le flux d’une requête. Cette fois, c’est une histoire statique, celle de la façon dont les données sont disposées sur le disque. La véritable identité du « Zone.Identifier » invisible attaché à un fichier téléchargé. La raison pour laquelle copier dix mille petits fichiers est tellement plus lent que copier un seul fichier de même taille totale. Jusqu’où « NTFS est journalisé, donc c’est sûr » est réellement vrai ── tout cela s’explique à partir de cette structure.
Ceci est la partie 5 de la série « Les profondeurs de l’I/O Windows ».
Prérequis pour ce volet : il est plus facile de suivre si vous avez déjà les bases des IRP et de la pile de périphériques vues dans la partie 1. Cela dit, pour que cet article puisse aussi se lire seul, voici d’abord les définitions des termes des volets précédents qui apparaissent dans le corps du texte.
| Terme | En une ligne | Pour en savoir plus |
|---|---|---|
| IRP (I/O Request Packet) | Le « bordereau de requête d’E/S » en lequel un appel d’API comme ReadFile est converti à l’intérieur du noyau. Les pilotes reçoivent ce bordereau et le traitent |
Partie 1 |
| Le gestionnaire d’E/S et la pile de périphériques | Le composant du noyau qui crée l’IRP et le transmet, dans l’ordre, à la pile de pilotes empilés jusqu’au périphérique visé — ainsi que cet empilement lui-même | Partie 1 |
| Le gestionnaire de cache | Le composant qui conserve le contenu d’un fichier en mémoire et écrit plus tard, groupé, le contenu des appels WriteFile sur le disque. La cause profonde du fait que « ce n’est pas parce que vous venez d’écrire que c’est déjà arrivé sur le disque » |
Partie 4 |
Tableau 1 : les termes des volets précédents supposés acquis dans ce volet
Autre point : les deux étapes vues dans la partie 1, cleanup (quand le dernier handle se ferme) et close (quand toutes les références internes au noyau ont disparu), seront aussi utilisées dans l’explication de la suppression de fichiers au chapitre 4.
1. La conclusion, d’abord
- Le cœur de NTFS, c’est la MFT (master file table). Tous les fichiers sont gérés comme des enregistrements du registre à l’intérieur de la MFT, et tout ce qui concerne un fichier se trouve soit « à l’intérieur de l’entrée de la MFT », soit « dans la zone hors MFT que désigne l’entrée » (chapitre 2).1
- La substance d’un fichier est « un ensemble d’attributs ». Un petit fichier tient entièrement, données comprises, dans son enregistrement MFT (il est résident) ; un gros fichier ne conserve qu’une référence à une suite de clusters (il est non résident). C’est ce qui explique la lenteur du traitement d’un grand nombre de petits fichiers (chapitre 2).1
- Un fichier peut avoir plusieurs flux de données (flux de données multiples). Les données habituelles constituent le « flux sans nom » ;
fichier.txt:nompermet d’ajouter des flux supplémentaires. C’est la véritable identité de Zone.Identifier (Mark of the Web) (chapitre 3).2 - Le nom aussi est un attribut. Attacher plusieurs noms à un même enregistrement, c’est un lien physique. Le nom court 8.3 cohabite lui aussi, comme « un nom de plus » (chapitre 4).34
- Le point d’analyse est le mécanisme officiel du « on ouvre ici, on se retrouve ailleurs ». Les liens symboliques, les jonctions et les fichiers à la demande de OneDrive sont tous des applications de cette même donnée étiquetée (chapitre 5).56
- Il existe deux journaux.
$LogFilesert à la restauration de la cohérence des métadonnées (un journal préalable pour ne pas se corrompre), tandis que le journal USN sert à l’enregistrement de l’historique des changements (un registre de ce qui a changé). Leurs rôles sont entièrement différents (chapitre 6).78 - « Taille » et « taille sur le disque » sont deux choses différentes. Les fichiers creux et la compression créent cet écart. C’est aussi ici que se trouve l’origine du fait, vu dans la partie 2, que « les fichiers compressés ne deviennent jamais asynchrones » (chapitre 7).910
2. Tout est un enregistrement de la MFT
2.1. Le registre du volume
Formater un volume NTFS crée la MFT (master file table), ainsi qu’une série de fichiers de métadonnées dont le nom commence par $. La MFT contient au moins une entrée pour chaque fichier du volume, et cela inclut une entrée pour la MFT elle-même.1
flowchart TB
subgraph VOL["Volume NTFS"]
MFT["$MFT ── la master file table<br/>Registre des enregistrements de tous les fichiers (elle-même incluse)"]
LOG["$LogFile ── journal de transactions<br/>des opérations de métadonnées (chapitre 6)"]
BITMAP["$Bitmap ── état d'utilisation des clusters"]
OTH["$Boot / $Secure / $UpCase, etc.<br/>Autres fichiers de métadonnées"]
DATA["Zone de données utilisateur<br/>(emplacement des données non résidentes)"]
end
MFT -->|"les enregistrements pointent vers l'emplacement"| DATA
Figure 1 : la structure d’un volume NTFS. Le principe de conception de NTFS est que même les informations de gestion du système de fichiers lui-même sont conservées sous forme de fichier.
Les informations concernant un fichier ── sa taille, ses horodatages, ses autorisations d’accès, et jusqu’au contenu des données ── sont soit stockées à l’intérieur de l’entrée de la MFT, soit stockées dans une zone hors MFT dont l’entrée décrit l’emplacement.1 Supprimer un fichier marque son entrée comme « libre » pour réutilisation, mais la MFT elle-même ne diminue jamais. Par ailleurs, une zone appelée zone MFT est réservée pour garder la MFT contiguë, et la documentation officielle va jusqu’à décrire tout le cycle de vie : à mesure que le volume se remplit, la fragmentation de la MFT commence.1
2.2. Un fichier, c’est un ensemble d’attributs — résident et non résident
Le contenu d’un enregistrement de fichier est une liste d’attributs : les informations standard (horodatages, etc.), le nom de fichier, la sécurité, et les données. C’est ici qu’intervient une bifurcation importante.
flowchart TB
subgraph REC["Enregistrement de fichier MFT (le registre d'un fichier)"]
STD["Attribut d'informations standard<br/>Horodatages, indicateurs d'attributs"]
FN["Attribut de nom de fichier<br/>(peut y en avoir plusieurs ── chapitre 4)"]
DATA["Attribut de données"]
end
Q{"Les données sont-elles petites ?"}
RES["Résident<br/>Les données elles-mêmes tiennent dans l'enregistrement<br/>La lecture se limite à un accès à la MFT"]
NONRES["Non résident<br/>L'enregistrement ne contient qu'une « référence à une suite de clusters »<br/>Les données réelles sont dans la zone de données utilisateur"]
DATA --> Q
Q -->|"Jusqu'à quelques centaines d'octets"| RES
Q -->|"Au-delà"| NONRES
Figure 2 : un enregistrement de fichier est un ensemble d’attributs. Si les données sont petites, elles « résident » à l’intérieur de l’enregistrement.
Il est plus parlant de comparer côte à côte comment le contenu d’un même enregistrement change entre résident et non résident.
flowchart LR
subgraph RES2["Résident ── petit fichier"]
RA["Enregistrement de fichier MFT (longueur fixe)<br/>Informations standard / Nom de fichier / Sécurité<br/>─────────────<br/>Attribut de données = le contenu lui-même<br/>« valeur=1 » vient se loger directement ici"]
RB["Aucun autre emplacement sur le disque<br/>La lecture se limite à un accès à la MFT"]
RA --> RB
end
subgraph NON2["Non résident ── gros fichier"]
NA["Enregistrement de fichier MFT (longueur fixe)<br/>Informations standard / Nom de fichier / Sécurité<br/>─────────────<br/>Attribut de données = table des runs de données<br/>La liste des « à partir d'où, combien de clusters »"]
NB["Zone de données utilisateur<br/>Run 1 : clusters contigus"]
NC["Zone de données utilisateur<br/>Run 2 : clusters contigus ailleurs"]
NA -->|"pointe vers l'emplacement"| NB
NA -->|"pointe vers l'emplacement"| NC
end
Figure 3 : résident et non résident, mis en regard. Pour un fichier non résident, l’enregistrement ne contient plus qu’un tableau (les runs de données) indiquant où se trouvent les données réelles et en quelle quantité.
Plus le nombre de runs de données augmente, plus il faut parcourir des zones dispersées pour lire un seul fichier. C’est la véritable identité de la fragmentation, dont il est question juste après.
Cette structure permet d’expliquer plusieurs phénomènes rencontrés sur le terrain.
- Pourquoi copier dix mille petits fichiers est lent. Chaque fichier déclenche des opérations de métadonnées ── création d’un enregistrement MFT, enregistrement du nom, définition de la sécurité. Le travail de tenue du registre finit par dominer sur le transfert de données lui-même (et chacune de ces opérations est aussi, comme nous le verrons en partie 6, un objet d’inspection pour les filtres).
- La véritable identité de la fragmentation. Les données non résidentes sont enregistrées comme « une suite de plages contiguës de clusters (runs) ». Quand on ne peut pas trouver de zone contiguë, le nombre de runs augmente, et le nombre de déplacements de tête nécessaires à la lecture augmente aussi ── c’est la fragmentation. Vous pouvez jeter un œil à la disposition réelle des runs avec
fsutil file layout. - Un « dossier » n’a rien de spécial non plus. Un répertoire est « un fichier qui contient un index allant du nom de fichier au numéro d’enregistrement MFT ». Sur le registre, tout repose sur le même mécanisme.
3. Les données ne sont qu’un « flux » parmi d’autres
3.1. Un fichier, plusieurs suites d’octets
Sous NTFS, un même fichier peut avoir plusieurs flux de données. Ce qu’on lit et écrit habituellement avec ReadFile/WriteFile est le flux par défaut, sans nom ; la syntaxe nom_de_fichier:nom_du_flux permet de créer un flux de données alternatif (ADS).2
flowchart LR
subgraph F["Un fichier nommé report.docx (un seul enregistrement MFT)"]
D0["Flux par défaut (sans nom)<br/>= le contenu habituellement visible"]
D1[":Zone.Identifier<br/>Information de provenance (Mark of the Web)"]
D2[":nom quelconque<br/>Information supplémentaire propre à une application"]
end
Figure 4 : les flux de données multiples. Seul le flux par défaut apparaît dans l’affichage de la taille de l’Explorateur.
L’ADS la plus familière est Zone.Identifier. Pour un fichier téléchargé via un navigateur, ce flux enregistre sa provenance (par exemple, le fait qu’il vient d’internet), et sert de preuve pour le message SmartScreen « Windows a protégé votre PC » ou pour l’affichage protégé d’Office. Nous avons traité la face visible de ce mécanisme dans « Pourquoi Windows affiche « Windows a protégé votre PC » » ── la face cachée n’était, en réalité, rien d’autre qu’un simple flux NTFS.
3.2. Les pièges pour les développeurs
- Invisible. Il n’apparaît ni dans la taille affichée par l’Explorateur, ni dans une liste
dir. Vous pouvez le vérifier avecdir /rou l’outilstreamsde Sysinternals.11 - Ne voyage pas. L’ADS étant une fonctionnalité de NTFS, elle a tendance à se perdre lors d’une copie vers une clé USB en FAT ou via un stockage cloud. C’est l’explication du « l’avertissement de téléchargement a disparu après la copie ».
- Peut aussi s’ouvrir depuis votre propre application. Il suffit d’inclure un deux-points dans le chemin, comme
CreateFile("data.txt:meta", ...), pour le lire et l’écrire.2 C’est pratique, mais on hérite du même coup de la propriété « ne voyage pas » vue au point précédent : ce n’est donc pas l’endroit où placer le corps de données métier.
4. Le nom est lui aussi un attribut ── liens physiques et noms 8.3
4.1. Les liens physiques ── plusieurs noms pour le même enregistrement
Nous avons noté à la figure 2 que « l’attribut de nom de fichier peut être présent plusieurs fois ». Au sein d’un même volume, plusieurs chemins qui référencent un seul et même fichier ── c’est cela, un lien physique (CreateHardLink / mklink /H).3
flowchart TB
subgraph DIR1["Index de C:\app\"]
E1["config.json → enregistrement n°1234"]
end
subgraph DIR2["Index de C:\backup\"]
E2["config-link.json → enregistrement n°1234"]
end
REC["Enregistrement MFT n°1234<br/>Contenu des données (ou référence à ses runs)<br/>Nombre de liens : 2"]
E1 --> REC
E2 --> REC
Figure 5 : un lien physique. Les index des répertoires pointent simplement vers le même enregistrement MFT ; les deux sont également « le vrai fichier ».
Comme il s’agit du même fichier quel que soit le nom par lequel on le modifie, le contenu correspond immédiatement d’un nom à l’autre.3 Et le sens de « suppression » change : DeleteFile signifie « détacher un nom », et l’entité elle-même ne disparaît qu’une fois le dernier nom détaché, tous les handles ouverts fermés, et jusqu’aux références internes au noyau — comme une section mappée en mémoire — également disparues. Les deux étapes vues en partie 1, cleanup (le dernier handle) et close (la dernière référence), s’appliquent donc telles quelles au cycle de vie de la suppression. Notez aussi que l’affichage des attributs a ses particularités : la documentation officielle signale que modifier un attribut via un lien peut laisser l’affichage apparent d’un autre lien obsolète.3
4.2. Le nom 8.3 ── un autre nom caché
Pour des raisons de compatibilité historique, NTFS peut générer automatiquement, pour un nom de fichier long, un nom court au format 8.3, comme REPORT~1.DOC. Celui-ci cohabite lui aussi dans l’enregistrement comme « un nom de plus ». Dans un dossier contenant un grand nombre de fichiers, la génération des noms courts et l’évitement des collisions devient coûteux : fsutil 8dot3name permet de désactiver la génération ou de supprimer les noms courts existants (point pratique à noter : comme une ancienne application qui enregistre un chemin de registre par son nom court peut se casser si on le supprime, il existe une fonction d’inspection à exécuter avant le strip).4
Ce qu’il faut noter ici, c’est que l’existence ou non d’un nom court dépend de l’environnement. Le comportement par défaut est déterminé par la valeur de registre NtfsDisable8dot3NameCreation, qui prend l’une de quatre valeurs : 0 (génération sur tous les volumes), 1 (aucune génération sur aucun volume), 2 (réglable par volume), et 3 (aucune génération en dehors du volume système).4 Comme la valeur 2 permet de basculer volume par volume, il n’est pas garanti que « sous Windows, un nom court comme PROGRA~1 existe toujours ». Avant d’écrire du code ou une procédure qui dépend des noms courts, vérifiez l’état actuel avec fsutil 8dot3name query C: (omettre le volume affiche le réglage par défaut commun à tous les volumes).
Les pièges autour des chemins et des noms (MAX_PATH, noms réservés, points en fin de nom) sont traités en détail dans « MAX_PATH et les pièges des chemins et noms de fichiers Windows ». En combinant la résolution de noms de la partie 1 (l’Object Manager) et ce chapitre (les noms à l’intérieur du système de fichiers), on obtient la vue d’ensemble complète des « noms » sous Windows.
5. Les points d’analyse ── le mécanisme du « on ouvre ici, on se retrouve ailleurs »
Un fichier ou un répertoire peut porter un point d’analyse (reparse point). Concrètement, il s’agit d’un attribut composé d’une étiquette (tag) plus des données définies par l’utilisateur. Quand le système de fichiers ouvre un fichier porteur d’un point d’analyse, le traitement est détourné selon l’étiquette ── soit un pilote filtre qui comprend l’étiquette prend le relais, soit, pour une étiquette de type redirection de nom, la résolution recommence avec le chemin cible.5
sequenceDiagram
participant App as Application
participant IOM as Gestionnaire d'E/S
participant FS as NTFS
App->>IOM: CreateFile("C:\data\link.txt")
IOM->>FS: IRP_MJ_CREATE (l'univers de la partie 1)
Note over FS: Trouve un point d'analyse sur la cible<br/>renvoie l'étiquette et ses données
alt Lien symbolique / jonction (redirection de nom)
FS-->>IOM: "Le véritable emplacement est ici"
IOM->>FS: Recommence la résolution avec le chemin cible
else Étiquette gérée par un filtre (fichiers cloud, etc.)
Note over FS: Un filtre qui comprend l'étiquette<br/>prend le relais (partie 6)
end
Figure 6 : la résolution d’un point d’analyse. C’est le crochet officiel qui intercepte l’opération « ouvrir ».
Sur ce mécanisme unique reposent plusieurs fonctionnalités familières.
- Le lien symbolique (
mklink) ── un panneau indicateur qui conserve le chemin cible. Il peut aussi pointer vers un autre volume ou un chemin UNC.6 - La jonction / le point de montage ── un mécanisme ancien qui relie un répertoire à un emplacement sur un autre volume local.3
- Les fichiers à la demande de OneDrive ── un fichier dont les données réelles ne sont pas présentes localement est représenté par un point d’analyse ; dès qu’on l’ouvre, un filtre le télécharge et en fournit le contenu. C’est la véritable identité du « c’est visible dans l’Explorateur, mais l’ouvrir déclenche du trafic réseau » (le mécanisme du filtre lui-même sera vu en partie 6).
Une seule mise en garde pratique : « ce qui se trouve au bout du chemin n’est pas forcément vraiment cet emplacement local ». Un outil qui parcourt récursivement une arborescence peut boucler sur une jonction, un calcul de taille totale peut compter en double, une sauvegarde peut déclencher une matérialisation massive de fichiers cloud ── un code qui ignore l’existence des points d’analyse tombe droit dans ces pièges. Vérifier l’attribut FILE_ATTRIBUTE_REPARSE_POINT renvoyé par les fonctions de la famille FindFirstFile est le point de départ pour s’en prémunir.5
6. Deux journaux ── $LogFile et l’USN
On dit souvent que « NTFS est un système de fichiers journalisé », mais NTFS possède en réalité deux journaux aux rôles différents. Les confondre conduit à mal lire ce qui est réellement garanti.
flowchart TB
subgraph J1["$LogFile ── journal préalable (pour ne pas se corrompre)"]
A1["Enregistre dans le journal, avant leur exécution,<br/>les opérations de métadonnées (mise à jour d'enregistrement, renommage, etc.)"]
A2["Au démarrage suivant après une défaillance système,<br/>rejoue le journal pour restaurer la cohérence de la structure"]
A1 --> A2
end
subgraph J2["Journal USN ── historique des changements (pour savoir ce qui a changé)"]
B1["À chaque changement sur un fichier ou un répertoire,<br/>enregistre le contenu du changement et le nom"]
B2["Permet aux outils de sauvegarde, d'indexation de recherche et de synchronisation<br/>de savoir « ce qui a changé depuis la dernière fois » sans balayage complet"]
B1 --> B2
end
Figure 7 : les deux journaux. $LogFile existe pour « ne pas se corrompre », l’USN pour « savoir ce qui a changé ».
Les différences se résument ainsi sous forme de tableau.
| Aspect | $LogFile (journal de transactions) |
Journal USN (journal des modifications) |
|---|---|---|
| Objectif | Ramener la structure du système de fichiers à un état cohérent après une défaillance7 | Savoir a posteriori « ce qui a changé depuis la dernière fois »8 |
| Ce qu’il enregistre | Un journal préalable des opérations de métadonnées (mise à jour d’enregistrement, renommage, etc.). Le contenu des fichiers n’est pas concerné | À chaque changement, la nature du changement et le nom du fichier/répertoire concerné8 |
| Qui l’utilise | NTFS lui-même, pour la restauration automatique au montage suivant | Des applications comme les outils de sauvegarde, d’indexation de recherche et de synchronisation |
| Jusqu’où peut-on remonter | Seulement ce qui est nécessaire à la restauration. Il réutilise une taille fixe, donc il ne peut pas servir à retracer un historique | Une fois la taille maximale visée (MaximumSize) dépassée, les enregistrements les plus anciens sont tronqués au moment du point de contrôle. La portée dépend du réglage de taille et du volume des mises à jour12 |
| Comment le consulter | Il n’existe pas de moyen officiel d’en lire le contenu (sa taille peut être vérifiée avec chkdsk /L) |
État avec fsutil usn queryjournal, contenu avec fsutil usn readjournal. En programmation, FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL12 |
| Peut-on le désactiver | Non, il fait partie de NTFS | Un administrateur peut le supprimer ou le désactiver, mais cela impose un balayage complet à tout service qui l’utilise, avec un impact important12 |
Tableau 2 : comparaison des deux journaux.
$LogFile(le journal de transactions) est le journal préalable des opérations de métadonnées. Même en cas de défaillance système, NTFS restaure automatiquement la cohérence du système de fichiers au démarrage suivant, à partir de ce journal et des informations de point de contrôle.7 Ce qui est protégé ici, c’est la structure. Comme nous l’avons vu en partie 4, le contenu des données sales dans le cache peut être perdu lors d’une coupure de courant ── la bonne lecture est : « le volume ne se corrompt pas, mais la dernière écriture peut disparaître ».- Le journal USN (journal des modifications) est un registre qui enregistre, à chaque changement sur un fichier ou un répertoire du volume, la nature du changement et le nom de la cible.8 C’est le mécanisme qui permet aux outils de sauvegarde et aux indexeurs de récupérer « seulement ce qui a changé depuis la dernière fois » sans balayage complet, et il sert aussi à éviter de reconstruire un index après une défaillance.8 En pratique, il est utile de se souvenir que
fsutil usn readjournalpeut servir à l’investigation, comme registre de recoupement pour compenser ce queFileSystemWatcherpeut manquer (voir « Guide pratique de FileSystemWatcher »).
7. Fichiers creux et compression ── l’histoire des deux « tailles »
Sous NTFS, la longueur logique d’un fichier et l’espace réellement alloué sont gérés séparément. Ce sont la « Taille » et la « Taille sur le disque » de la boîte de dialogue Propriétés. Deux causes principales créent cet écart.
Un fichier creux (sparse) n’alloue pas d’espace réel aux plages qui ne contiennent que des zéros ; il les gère comme des « trous ».9 Il est parfaitement courant qu’un fichier de disque virtuel de 42 Go en taille logique n’occupe que 500 Mo sur le disque. Lire un trou renvoie des zéros, et y écrire alloue exactement l’espace écrit.
flowchart LR
subgraph L["Fichier logique (taille : 1 Go)"]
R1["Données 10 Mo"]
H1["Trou (zéros) 500 Mo"]
R2["Données 5 Mo"]
H2["Trou (zéros) le reste"]
end
subgraph P["Allocation sur le disque (15 Mo + informations de gestion)"]
A1["Run : le contenu de R1"]
A2["Run : le contenu de R2"]
end
R1 --> A1
R2 --> A2
Figure 8 : un fichier creux. Un « trou » n’a pas d’allocation, ce qui écarte la taille logique de la taille sur le disque.
La compression NTFS compresse et stocke les données par unité de compression.10 C’est transparent et pratique, mais le coût, lui, n’est pas transparent ── décompression et recompression s’exécutent à chaque lecture et écriture, et la fragmentation progresse aussi plus facilement. Et comme nous l’avons vu au chapitre 5 de la partie 2, l’accès à un fichier compressé ne devient jamais asynchrone (le système de fichiers le convertit en synchrone). C’est l’un des endroits à suspecter quand « certains fichiers ne deviennent pas plus rapides malgré le passage en E/S asynchrones ».
La taille réelle basée sur l’allocation peut être obtenue avec GetCompressedFileSize. Pour une investigation où « le total des tailles de fichiers » ne correspond pas à « l’utilisation du disque », la pratique classique consiste à suspecter, dans l’ordre, quatre causes : fichiers creux, compression, ADS (chapitre 3), et arrondi au cluster.
8. Vérifiez par vous-même
Comme d’habitude, tout ceci peut s’observer directement sur votre propre machine Windows (certaines commandes nécessitent des droits administrateur). Pour que vous puissiez juger vous-même si les résultats sont corrects, chaque commande est accompagnée d’une note indiquant où regarder et ce que cela révèle.
:: Voir les flux de données alternatifs
dir /r C:\Users\%USERNAME%\Downloads
Ce qu’il faut regarder : sous la ligne du fichier normal, une ligne indentée de la forme nom_de_fichier:Zone.Identifier:$DATA apparaît, avec sa longueur. Si cette ligne est présente, le fichier porte le Mark of the Web (chapitre 3). Les fichiers téléchargés via un navigateur l’ont, ceux que vous avez créés vous-même ne l’ont pas. Exécutez la commande dans les deux emplacements et comparez : la présence ou non de l’ADS devient évidente.
:: Voir la disposition (runs) et les attributs d'un fichier sur la MFT
fsutil file layout C:\path\to\file.dat
:: Voir uniquement les extents (une sous-commande documentée officiellement)
fsutil file queryextents C:\path\to\file.dat
Ce qu’il faut regarder : layout liste, pour chaque flux, la taille, la taille allouée, et, si non résident, la liste des extents (chacun un triplet VCN, LCN, nombre de clusters). Un fichier minuscule qui n’affiche aucune ligne d’extent est résident (section 2.2) ; s’il est réparti sur plusieurs lignes, il est fragmenté. Exécuter la commande sur un fichier texte de quelques octets puis sur un fichier de plusieurs centaines de Mo, et comparer, est le moyen le plus rapide de ressentir concrètement la différence entre résident et non résident.
:: Le réglage de génération des noms courts 8.3, et les noms courts existants
fsutil 8dot3name query C:
dir /x
Ce qu’il faut regarder : query indique si la génération des noms courts est activée ou désactivée pour ce volume (omettre le volume affiche le réglage par défaut commun à tous les volumes).4 dir /x affiche une colonne de nom court à côté du nom long : si la colonne est vide, aucun nom court n’a été créé. Vous pouvez ainsi vérifier sur votre propre environnement ce que la section 4.2 appelait « l’existence d’un nom court n’est pas garantie ».
:: L'état du journal USN
fsutil usn queryjournal C:
Ce qu’il faut regarder : la commande affiche l’ID du journal, la plage valide des USN (First USN / Next USN), la taille maximale visée (MaximumSize) et l’unité d’allocation (AllocationDelta).12 Créez un fichier puis relancez la commande : Next USN devrait avoir avancé, ce qui confirme que « les changements sont enregistrés ». MaximumSize donne un ordre de grandeur de « jusqu’où on peut remonter », évoqué au chapitre 6. Sur un volume où le journal est désactivé, la commande renvoie une erreur.
:: Vérifier les points d'analyse (cible et étiquette)
dir /aL C:\Users\%USERNAME%
fsutil reparsepoint query "C:\Users\%USERNAME%\OneDrive"
Ce qu’il faut regarder : ce qui apparaît dans dir /aL est un point d’analyse (celui pour lequel FILE_ATTRIBUTE_REPARSE_POINT est positionné). Les liens symboliques et les jonctions s’affichent avec un type comme <SYMLINKD> ou <JUNCTION>. fsutil reparsepoint query affiche la valeur de l’étiquette de reparse et, pour une étiquette de type redirection de nom, le chemin cible. Pointer la commande vers une cible qui n’est pas un point d’analyse renvoie une erreur : obtenir une erreur est donc elle-même la confirmation qu’« il s’agit ici d’un dossier ordinaire ».
En suivant les opérations sur les fichiers avec Procmon, les personnages de cet article défilent sous leur vrai nom (écritures dans $LogFile, chemins portant un nom de flux, traitement des points d’analyse). Pour son utilisation, voir « Guide pratique de Process Monitor (ProcMon) ».
9. Résumé
- Le cœur de NTFS, c’est la MFT. Chaque fichier est un enregistrement du registre, et l’information se trouve soit « à l’intérieur de l’enregistrement », soit « dans la zone externe que désigne l’enregistrement ». Les petites données sont résidentes, les grandes données sont référencées par des runs : la lenteur du traitement d’un grand nombre de petits fichiers, tout comme la fragmentation, sont des conséquences de cette structure.1
- Un fichier peut avoir plusieurs flux de données. Zone.Identifier (Mark of the Web) n’est rien d’autre qu’une ADS : elle se voit avec
dir /r, et ne voyage pas hors de NTFS.211 - Le nom est un attribut, et il peut y en avoir plusieurs. Un lien physique est un nom de même rang pointant vers le même enregistrement, le nom 8.3 est un nom de compatibilité supplémentaire. « Suppression » signifie « détacher un nom », et l’entité elle-même ne disparaît que lorsque le dernier nom, le dernier handle et toutes les références internes au noyau (section mappée, etc.) ont disparu.34
- Le point d’analyse est le crochet officiel de l’« ouverture », et les liens symboliques, les jonctions et les fichiers à la demande en sont tous des applications. Un code qui parcourt une arborescence doit être conscient de
FILE_ATTRIBUTE_REPARSE_POINT.56 - Il y a deux journaux.
$LogFilesert à la restauration de la cohérence structurelle (pour ne pas se corrompre), l’USN sert à l’historique des changements (ce qui a changé). « C’est journalisé, donc les données aussi sont sûres » est faux ── la durabilité des données se construit avec les outils vus en partie 4.78 - La taille logique et l’allocation sont deux choses distinctes. Fichiers creux, compression, ADS et arrondi au cluster sont les quatre grandes causes du « les tailles ne correspondent pas ». Avec le fait que les fichiers compressés ne deviennent jamais asynchrones, c’est un ensemble d’outils à garder sous la main pour les investigations de performance.910
La suite, et le dernier volet, sera la partie 6 : « Pilotes filtres et minifiltres ── pourquoi Procmon et les antivirus peuvent intercepter les E/S ». Comment les « intermédiaires » apparus par intermittence depuis la partie 1 ── antivirus, Procmon, OneDrive, chiffrement ── interceptent-ils réellement les E/S ? En guise de point d’orgue de la série, nous révélerons la véritable identité des habitants installés dans les interstices de la pile de périphériques.
Articles connexes
- Les profondeurs de l’I/O Windows (partie 1) — Chaque lecture et écriture devient un IRP : la vue d’ensemble du système d’E/S
- Les profondeurs de l’I/O Windows (partie 2) — E/S synchrones et asynchrones : ce que signifie vraiment OVERLAPPED
- Les profondeurs de l’I/O Windows (partie 4) — Le gestionnaire de cache : quand votre WriteFile atteint-il réellement le disque ?
- Pourquoi Windows affiche « Windows a protégé votre PC »
- MAX_PATH et les pièges des chemins et noms de fichiers Windows — la limite de 260 caractères, les noms réservés, les points de fin et la casse
- Guide pratique de FileSystemWatcher - Gérer les événements manqués et les doublons
- Les pièges des lecteurs réseau et des chemins UNC — Travailler avec un serveur de fichiers (dossier partagé) depuis une application métier
- Guide pratique de Process Monitor (ProcMon) — identifier en 10 minutes un « paramètre non pris en compte » ou un ACCESS DENIED
Domaines de conseil associés
Komura Software LLC prend en charge la conception et l’investigation des applications métier Windows dont les comportements déroutants — taille de fichier, performances de copie, bugs liés aux liens ou aux flux — trouvent leur origine dans le fonctionnement de NTFS.
- Développement d’applications Windows
- Investigation de bugs et analyse de cause racine
- Réutilisation des actifs existants et accompagnement à la migration
- Contact
Références
-
Microsoft Learn, Master File Table. Sur le fait que chaque fichier d’un volume NTFS possède au moins une entrée dans la MFT, y compris une entrée pour la MFT elle-même ; que toutes les informations concernant un fichier — taille, horodatages, autorisations d’accès et contenu des données — sont stockées soit dans l’entrée de la MFT, soit dans une zone hors MFT dont l’entrée décrit l’emplacement ; que la suppression d’un fichier marque son entrée comme libre pour réutilisation sans réduire la taille de la MFT ; qu’une zone MFT est réservée pour garder la MFT contiguë ; et que la fragmentation de la MFT survient à mesure que l’allocation progresse. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, File Streams. Sur le fait que les données d’un fichier NTFS sont stockées sous forme d’un ou plusieurs flux, qu’il existe un flux de données par défaut (sans nom) et des flux de données alternatifs nommés, et sur la possibilité d’ouvrir un flux avec CreateFile en utilisant la syntaxe « nom_de_fichier:nom_du_flux ». ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Hard links and junctions. Sur le fait qu’un lien physique est une représentation au niveau du système de fichiers dans laquelle plusieurs chemins d’un même volume référencent un seul fichier, créée avec CreateHardLink ; que les modifications effectuées via n’importe quel lien sont immédiatement visibles via les autres ; que les modifications d’attributs se propagent à tous les liens physiques, tandis que l’affichage au niveau de l’entrée de répertoire a la particularité de ne se mettre à jour que pour le lien via lequel la modification a été effectuée ; et sur les jonctions (un mécanisme reliant un répertoire à un autre volume local). ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, fsutil 8dot3name. Sur le fait que NTFS peut générer un nom court au format 8.3 pour un nom de fichier long, et que fsutil 8dot3name permet d’interroger et de définir l’activation ou la désactivation de la génération des noms courts, de supprimer (strip) les noms courts existants, et de balayer les références de registre affectées par cette suppression. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Reparse points. Sur le fait qu’un point d’analyse est un ensemble de données définies par l’utilisateur accompagnées d’une étiquette de reparse identifiant de façon unique le format de ces données ; que le système de fichiers tente, à l’ouverture d’un fichier porteur d’un point d’analyse, le traitement associé à l’étiquette (pris en charge par un filtre de système de fichiers qui interprète l’étiquette) ; que ce mécanisme sert à l’implémentation des liens du système de fichiers NTFS et du stockage distant (stockage hiérarchique) ; et sur la vérification de sa présence via l’attribut FILE_ATTRIBUTE_REPARSE_POINT. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Symbolic links. Sur le fait qu’un lien symbolique est un objet du système de fichiers qui pointe vers un autre fichier ou répertoire, fonctionnant comme une redirection transparente vers la cible ; sur l’existence de liens absolus et relatifs ; et sur la possibilité de référencer un autre volume ou un chemin distant. ↩ ↩2 ↩3
-
Microsoft Learn, NTFS overview. Sur le fait que NTFS utilise un fichier journal et des informations de point de contrôle pour restaurer automatiquement la cohérence du système de fichiers au démarrage suivant, en rejouant le journal de transactions en cas de défaillance système, ainsi que sur son remappage dynamique des secteurs défectueux et le mécanisme self-healing NTFS qui répare en arrière-plan les corruptions mineures. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Change Journals. Sur le fait qu’à chaque modification d’un fichier ou d’un répertoire sur un volume, la nature du changement et le nom du fichier/répertoire concerné sont enregistrés dans le journal des modifications USN de ce volume ; qu’un journal est maintenu par volume ; et sur son utilisation pour restaurer l’index du système de fichiers après une défaillance, en évitant une réindexation complète du volume. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Sparse Files. Sur le fait qu’un fichier creux n’alloue pas d’espace disque physique aux grandes plages composées de zéros, n’allouant de l’espace qu’aux portions contenant des données, et que la lecture d’une plage non allouée renvoie des zéros. ↩ ↩2 ↩3
-
Microsoft Learn, File Compression and Decompression. Sur le fait que la compression de fichiers NTFS s’effectue de façon transparente, les données étant compressées et stockées par unité de compression ; sur la récupération de la taille après compression (réellement allouée) avec GetCompressedFileSize ; et sur le coût de décompression/recompression associé à la lecture et à l’écriture d’un fichier compressé. ↩ ↩2 ↩3
-
Microsoft Learn, Streams - Sysinternals. Sur le fait que l’utilitaire streams de Sysinternals permet d’énumérer et de supprimer les flux de données alternatifs des fichiers NTFS. ↩ ↩2
-
Microsoft Learn, Creating, Modifying, and Deleting a Change Journal et fsutil usn. Sur le fait que le MaximumSize du journal des modifications est une valeur cible, le journal étant tronqué au moment du point de contrôle NTFS une fois sa taille supérieure à la somme de MaximumSize et d’AllocationDelta ; qu’AllocationDelta est l’unité d’ajout en fin et de suppression en tête du journal ; que fsutil usn queryjournal affiche l’état et la capacité du journal, et readjournal son contenu ; sur l’accès programmatique via FSCTL_CREATE_USN_JOURNAL / FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL / FSCTL_DELETE_USN_JOURNAL ; et sur le fait que la suppression ou la désactivation d’un journal actif entraîne un balayage complet de la MFT et impose une nouvelle analyse du volume à tout service utilisant le journal. ↩ ↩2 ↩3 ↩4
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Les profondeurs de l'E/S Windows (épisode 4) — Le gestionnaire de cache : quand votre WriteFile atteint-il vraiment le disque ?
Quatrième épisode d'une série qui explique en images le gestionnaire de cache de Windows. Cet article détaille le cache implémenté comme ...
Les profondeurs de l'I/O Windows (partie 1) — Chaque lecture et écriture devient un IRP : la vue d'ensemble du système d'E/S
Premier volet d'une série qui explique le système d'E/S de Windows en partant de la base. Nous cartographions l'espace de noms de l'Objec...
Les profondeurs de l'I/O Windows (partie 6, dernière partie) — Pilotes filtres et minifiltres : pourquoi Procmon et les antivirus peuvent intercepter vos E/S
Dernier volet d'une série qui explique à l'aide de schémas les pilotes de filtre et les minifiltres de Windows. Nous y détaillons le Filt...
Les profondeurs de l'I/O Windows (partie 2) — E/S synchrones et asynchrones : ce que signifie vraiment OVERLAPPED
Deuxième volet d'une série qui explique en schémas l'E/S synchrone et l'E/S asynchrone (E/S overlapped) de Windows. Nous y détaillons le ...
Bonnes pratiques de multithreading en pratique — édition .NET : ce qu'il faut décider avant d'ajouter des threads
Un ensemble de bonnes pratiques de conception pour .NET/C# afin d'éviter que « démarrer un thread » ne fasse planter ou geler l'applicati...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Qu'est-ce que la MFT (master file table) ?
- C'est la structure de données au cœur d'un volume NTFS : un registre qui contient au moins une entrée (un enregistrement de fichier) pour chaque fichier du volume, y compris une entrée pour la MFT elle-même. Tout ce qui concerne un fichier — sa taille, ses horodatages, ses autorisations d'accès, et jusqu'au contenu des données lui-même — est stocké soit à l'intérieur d'une entrée de la MFT, soit dans une zone hors MFT que l'entrée désigne. Un petit fichier tient entièrement, données comprises, dans son entrée de MFT (il est résident) ; un gros fichier ne conserve dans son entrée qu'une référence à l'emplacement de ses données (une suite de clusters) (il est non résident). Supprimer un fichier marque son entrée comme libre pour réutilisation, mais la taille de la MFT elle-même ne diminue jamais.
- Qu'est-ce que la donnée invisible « Zone.Identifier » attachée à certains fichiers ?
- C'est l'un des flux de données multiples de NTFS (flux de données alternatifs). Sous NTFS, un même fichier peut contenir plusieurs suites d'octets (flux) ; ce que l'on lit et écrit habituellement est le flux par défaut, sans nom. Dans un flux supplémentaire désigné par deux-points, comme « file.txt:Zone.Identifier », Windows enregistre la provenance du fichier (par exemple, le fait qu'il a été téléchargé depuis internet). C'est ce qu'on appelle le « Mark of the Web », un élément utilisé par SmartScreen et par l'affichage protégé d'Office pour émettre leurs avertissements. Les flux alternatifs n'apparaissent pas dans l'affichage de la taille de l'Explorateur ; on peut les vérifier avec la commande dir /r ou l'outil streams de Sysinternals. Notez aussi qu'ils ne sont pas conservés lors d'une copie vers un système de fichiers autre que NTFS, comme FAT.
- Quelle est la différence entre un lien physique et un lien symbolique ?
- Un lien physique consiste à « ajouter un nom de plus, de même rang, pointant vers le même fichier réel (le même enregistrement MFT) ». Il ne peut être créé qu'au sein d'un même volume ; quel que soit le nom utilisé pour y accéder, c'est le même fichier, et supprimer un nom ne fait pas disparaître le fichier tant qu'un autre nom subsiste. Un lien symbolique est « un panneau indicateur qui redirige vers un autre chemin », implémenté comme un point d'analyse. Comme il ne conserve que la chaîne de caractères du chemin cible, il peut pointer vers un autre volume ou un emplacement distant, mais devient une impasse si la cible disparaît. En pratique, la règle de base est la suivante : le lien physique partage l'entité réelle (ce qui change le sens de la suppression), le lien symbolique redirige un chemin (pour un déplacement ou une redirection).
- NTFS est un système de fichiers journalisé : cela signifie-t-il que les données ne disparaissent jamais lors d'une coupure de courant ?
- Il faut comprendre précisément ce qui est protégé. Ce que protège le journal de transactions de NTFS ($LogFile), c'est la cohérence de la structure du système de fichiers (ses métadonnées). Même en cas de défaillance système, NTFS restaure automatiquement la cohérence à l'aide du journal au démarrage suivant, ce qui évite que le volume ne devienne corrompu et illisible. Mais cela ne signifie pas que le contenu même du fichier en cours d'écriture est restauré. Comme nous l'avons vu dans le quatrième volet de la série, les données sales présentes dans le cache sont perdues en cas de coupure de courant. Autrement dit, la bonne compréhension est : « le volume ne se corrompt pas, mais le contenu de la dernière écriture peut disparaître » — si vous avez besoin de la durabilité des données elles-mêmes, il faut la construire vous-même, avec FlushFileBuffers, WRITE_THROUGH, ou une conception d'écriture côté application (fichier temporaire puis renommage, etc.).
- Pourquoi la « taille » d'un fichier diffère-t-elle de sa « taille sur le disque » ?
- Parce que NTFS gère séparément la longueur logique d'un fichier et l'espace disque réellement alloué. Même un fichier ordinaire présente un léger écart, car l'allocation est arrondie à l'unité de cluster (4 Ko par défaut), mais l'écart devient important pour les fichiers creux (sparse) et les fichiers compressés. Un fichier creux n'alloue pas d'espace réel aux plages qui ne contiennent que des zéros ; il les gère comme des « trous » — il est donc parfaitement possible qu'un fichier de plusieurs gigaoctets en taille logique n'occupe que quelques mégaoctets sur le disque. Un fichier compressé n'a que sa taille après compression qui est allouée. À l'inverse, si la « taille sur le disque » paraît plus grande, la cause est souvent l'arrondi au cluster ou un flux de données alternatif.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.