J'avais l'habitude de penser que les modifications de fichier sont enregistrées directement sur le disque, c'est-à-dire dès que je ferme le fichier et décide de cliquer/sélectionner enregistrer. Cependant, dans une récente conversation, un de mes amis m'a dit que ce n'est généralement pas vrai; le système d'exploitation (en particulier, nous parlions de systèmes Linux) conserve les modifications en mémoire et il a un démon qui écrit réellement le contenu de la mémoire sur le disque.
Il a même donné l'exemple des lecteurs flash externes: ceux-ci sont montés dans le système (copiés dans la mémoire) et parfois la perte de données se produit parce que le démon n'a pas encore enregistré le contenu dans la mémoire flash; c'est pourquoi nous démontons les lecteurs flash.
Je n'ai aucune connaissance du fonctionnement des systèmes d'exploitation, et donc je n'ai absolument aucune idée si cela est vrai et dans quelles circonstances. Ma question principale est: cela se produit-il comme décrit dans les systèmes Linux/Unix (et peut-être d'autres OS)? Par exemple, cela signifie-t-il que si j'éteins l'ordinateur immédiatement après avoir modifié et enregistré un fichier, mes modifications seront très probablement perdues? Cela dépend peut-être du type de disque - disques durs traditionnels ou disques SSD?
La question se réfère spécifiquement aux systèmes de fichiers qui ont un disque pour stocker les informations, même si toute clarification ou comparaison est bien reçue.
si j'éteins l'ordinateur immédiatement après avoir modifié et enregistré un fichier, mes modifications seront-elles probablement perdues?
Ils pourraient être. Je ne dirais pas "très probablement", mais la probabilité dépend de beaucoup de choses.
Un moyen simple d'augmenter les performances d'écriture de fichiers consiste pour le système d'exploitation à simplement mettre en cache les données, à dire (mentir) à l'application que l'écriture a traversée, puis à effectuer l'écriture plus tard. Ceci est particulièrement utile s'il y a une autre activité de disque en cours en même temps: le système d'exploitation peut prioriser les lectures et effectuer les écritures plus tard. Cela peut également supprimer complètement la nécessité d'une écriture réelle, par exemple, dans le cas où un fichier temporaire est supprimé rapidement par la suite.
Le problème de mise en cache est plus prononcé si le stockage est lent. La copie de fichiers d'un SSD rapide vers une clé USB lente impliquera probablement beaucoup de mise en cache d'écriture, car la clé USB ne peut tout simplement pas suivre. Mais votre commande cp
revient plus rapidement, vous pouvez donc continuer à travailler, voire éditer les fichiers qui viennent d'être copiés.
Bien sûr, la mise en cache comme celle-ci a l'inconvénient que vous remarquez, certaines données peuvent être perdues avant qu'elles ne soient réellement enregistrées. L'utilisateur sera vexé si son éditeur lui dit que l'écriture a réussi, mais que le fichier n'était pas réellement sur le disque. C'est pourquoi il y a fsync()
appel système , qui est censé retourner uniquement après que le fichier a réellement atteint le disque. Votre éditeur peut l'utiliser pour s'assurer que les données sont correctes avant de signaler à l'utilisateur que l'écriture a réussi.
J'ai dit "est censé", car le lecteur lui-même pourrait dire les mêmes mensonges au système d'exploitation et dire que l'écriture est terminée, alors que le fichier n'existe vraiment que dans un cache d'écriture volatile au sein du lecteur. Selon le lecteur, il n'y a peut-être pas moyen de contourner cela.
En plus de fsync()
, il existe également les appels système sync()
et syncfs()
qui demandent au système de s'assurer que toutes les écritures à l'échelle du système ou toutes les écritures sur un particulier système de fichiers a atteint le disque. L'utilitaire sync
peut être utilisé pour les appeler.
Ensuite, il y a aussi l'indicateur O_DIRECT
Sur open()
, qui est censé "essayer de minimiser les effets de cache des E/S vers et depuis ce fichier". La suppression de la mise en cache réduit les performances, ce qui est principalement utilisé par les applications (bases de données) qui font leur propre mise en cache et veulent en avoir le contrôle. (O_DIRECT
N'est pas sans problèmes, les commentaires à ce sujet dans la page de manuel sont quelque peu amusants.)
Ce qui se passe lors d'une mise hors tension dépend également du système de fichiers. Ce ne sont pas seulement les données de fichiers qui devraient vous préoccuper, mais les métadonnées du système de fichiers. Avoir les données du fichier sur le disque n'est pas très utile si vous ne les trouvez pas. L'extension d'un fichier à une plus grande taille nécessitera l'allocation de nouveaux blocs de données, et ils doivent être marqués quelque part.
La façon dont un système de fichiers traite les modifications de métadonnées et l'ordre entre les métadonnées et les écritures de données varie beaucoup. Par exemple, avec ext4
, Si vous définissez l'indicateur de montage data=journal
, Toutes les écritures - même les écritures de données - passent par le journal et devraient être plutôt sûres. Cela signifie également qu'ils sont écrits deux fois, donc les performances diminuent. Les options par défaut essaient de classer les écritures afin que les données se trouvent sur le disque avant la mise à jour des métadonnées. D'autres options ou d'autres systèmes de fichiers peuvent être meilleurs ou pires; Je n'essaierai même pas une étude approfondie.
En pratique, sur un système légèrement chargé, le fichier doit frapper le disque en quelques secondes. Si vous avez affaire à un stockage amovible, démontez le système de fichiers avant de retirer le support pour vous assurer que les données sont bien envoyées au lecteur, et il n'y a plus d'activité. (Ou demandez à votre environnement GUI de le faire pour vous.)
Il existe un moyen extrêmement simple de prouver qu'il ne peut pas être vrai que les modifications de fichiers sont toujours directement enregistrées sur le disque, à savoir le fait qu'il existe des systèmes de fichiers qui ne sont pas sauvegardés par un disque en premier lieu . Si un système de fichiers n'a pas de disque en premier lieu, alors il ne peut pas écrire les modifications sur le disque, jamais .
Quelques exemples sont:
tmpfs
, un système de fichiers qui n'existe que dans RAM (ou plus précisément, dans le cache du tampon)ramfs
, un système de fichiers qui n'existe qu'en RAMsysfs
, procfs
, devfs
, shmfs
, …)Mais même pour les systèmes de fichiers sur disque, ce n'est généralement pas vrai. La page Comment corrompre une base de données SQLite contient un chapitre appelé Échec de synchronisation qui décrit de nombreuses manières différentes dont les écritures (dans ce cas, commettent sur une base de données SQLite) peuvent ne pas arriver sur le disque. SQLite a également un livre blanc expliquant les nombreux cercles que vous devez franchir pour garantir Commit atomique dans SQLite . (Notez que Écriture atomique est un problème beaucoup plus difficile que juste Écriture , mais bien sûr, l'écriture sur le disque est un sous-problème de l'écriture atomique, et vous pouvez aussi en apprendre beaucoup sur ce problème dans cet article.) Cet article contient une section sur ( Choses qui peuvent mal tourner qui comprend une sous-section sur vidages de disque incomplets = qui donnent quelques exemples de subtilités subtiles qui pourraient empêcher une écriture d'atteindre le disque (comme le contrôleur du disque dur signalant qu'il a écrit sur le disque alors qu'il ne l'a pas fait - oui, il existe des fabricants de disques durs qui le font, pourrait même être légale selon la spécification ATA, car elle est formulée de manière ambiguë à cet égard).
Il est vrai que la plupart des systèmes d'exploitation, y compris Unix, Linux et Windows, utilisent un cache d'écriture pour accélérer les opérations. Cela signifie qu'éteindre un ordinateur sans l'arrêter est une mauvaise idée et peut entraîner une perte de données. Il en va de même si vous supprimez un stockage USB avant qu'il ne soit prêt à être retiré.
La plupart des systèmes offrent également la possibilité de rendre les écritures synchrones. Cela signifie que les données seront sur le disque avant qu'une application ne reçoive une confirmation de réussite, au prix d'être plus lente.
En bref, il y a une raison pour laquelle vous devez éteindre correctement votre ordinateur et préparer correctement le stockage USB pour le retrait.
Cela dépend-il du type de disque (disques durs traditionnels vs disques SSD) ou de toute autre variable que je ne connais pas? Est-ce que cela se produit (si c'est le cas) uniquement sous Linux ou est-ce présent dans d'autres systèmes d'exploitation?
Lorsque vous avez le choix, vous ne devez pas permettre au stockage basé sur flash de perdre de l'énergie sans un arrêt propre.
Sur le stockage à faible coût comme les cartes SD, vous pouvez vous attendre à perdre des blocs d'effacement entiers (plusieurs fois plus grands que 4 Ko), perdant des données qui pourraient appartenir à différents fichiers ou à des structures essentielles du système de fichiers.
Certains SSD coûteux peuvent prétendre offrir de meilleures garanties en cas de panne de courant. Cependant, des tests tiers suggèrent que de nombreux SSD coûteux ne le font pas. La couche qui remappe les blocs pour le "nivellement d'usure" est complexe et exclusive. Les pannes possibles incluent la perte de toutes les données sur le disque.
En appliquant notre cadre de test, nous testons 17 SSD de base de six fournisseurs différents en utilisant plus de trois mille cycles d'injection de pannes au total. Nos résultats expérimentaux révèlent que 14 des 17 périphériques SSD testés présentent des comportements de défaillance surprenants en cas de panne de courant, notamment la corruption de bits, les écritures tondues, les écritures non sérialisables, la corruption de métadonnées et la défaillance totale des périphériques.
2017: https://dl.acm.org/citation.cfm?id=2992782&preflayout=flat
Les disques durs tournants ont des caractéristiques différentes. Pour des raisons de sécurité et de simplicité, je recommande de supposer qu'ils présentent la même incertitude pratique que le stockage flash.
Sauf si vous avez des preuves spécifiques, ce que vous n'avez clairement pas. Je n'ai pas de chiffres comparatifs pour faire tourner les disques durs.
Un disque dur peut laisser un secteur incomplètement écrit avec une mauvaise somme de contrôle, ce qui nous donnera un échec de lecture agréable plus tard. D'une manière générale, ce mode de défaillance des disques durs est tout à fait attendu; les systèmes de fichiers Linux natifs sont conçus dans cet esprit. Ils visent à préserver le contrat de fsync()
face à ce type de panne de courant. (Nous aimerions vraiment que cela soit garanti sur les SSD).
Cependant, je ne sais pas si les systèmes de fichiers Linux y parviennent dans tous les cas, ou si c'est même possible.
Le prochain démarrage après ce type de panne peut nécessiter une réparation du système de fichiers. Ceci étant Linux, il est possible que la réparation du système de fichiers pose des questions que vous ne comprenez pas, où vous ne pouvez qu'appuyer sur Y et espérer que cela se résoudra.
Le contrat fsync () est à la fois une bonne et une mauvaise nouvelle. Vous devez d'abord comprendre la bonne nouvelle.
Bonne nouvelle: fsync()
est bien documenté comme la bonne façon d'écrire des données de fichier, par exemple lorsque vous appuyez sur "enregistrer". Et il est largement admis que par ex. les éditeurs de texte doivent remplacer les fichiers existants de manière atomique à l'aide de rename()
. Ceci est destiné à vous assurer que vous conservez toujours l'ancien fichier ou que vous obtenez le nouveau fichier (qui était fsync()
éd avant le changement de nom). Vous ne voulez pas vous retrouver avec une version à moitié écrite du nouveau fichier.
Mauvaise nouvelle: pendant de nombreuses années, appeler fsync () sur le système de fichiers Linux le plus populaire pourrait effectivement laisser le système entier suspendu pendant des dizaines de secondes. Étant donné que les applications ne peuvent rien y faire, il était très courant d'utiliser de façon optimiste rename () sans fsync (), qui semblait relativement fiable sur ce système de fichiers.
Par conséquent, il existe des applications qui n'utilisent pas correctement fsync ().
La version suivante de ce système de fichiers évitait généralement le blocage de fsync () - en même temps qu'elle commençait à s'appuyer sur l'utilisation correcte de fsync ().
C'est assez mauvais. La compréhension de cette histoire n'est probablement pas aidée par le ton dédaigneux et l'invective qui a été utilisé par de nombreux développeurs de noyaux en conflit.
La résolution actuelle est que le système de fichiers Linux le plus populaire prend par défaut en charge le modèle rename () sans nécessiter fsync () implémente la "compatibilité bogue pour bogue" avec la version précédente. Cela peut être désactivé avec l'option de montage noauto_da_alloc
.
Ce n'est pas une protection complète. Fondamentalement, il vide le IO au moment de renommer (), mais il n'attend pas que le IO se termine avant de renommer. C'est bien mieux que par exemple une fenêtre de danger de 60 secondes cependant! Voir aussi la réponse à Quels systèmes de fichiers nécessitent fsync () pour la sécurité en cas de crash lors du remplacement d'un fichier existant par rename ()?
Certains systèmes de fichiers moins répandus n'offrent pas de protection. XFS refuse de le faire. Et UBIFS ne l'a pas non plus implémenté, apparemment il pourrait être accepté mais a besoin de beaucoup de travail pour le rendre possible. La même page souligne que UBIFS a plusieurs autres problèmes "TODO" pour l'intégrité des données, y compris sur la perte de puissance. UBIFS est un système de fichiers utilisé directement sur le stockage flash. J'imagine que certaines des difficultés mentionnées par UBIFS avec le stockage flash pourraient être pertinentes pour les bogues SSD.
Sur un système légèrement chargé, le noyau laissera les données de fichier nouvellement écrites dans le cache de page pendant environ 30 secondes après une write()
, avant de les vider sur le disque, pour optimiser le cas où elles sont supprimées ou modifié à nouveau bientôt.
Par défaut, dirty_expire_centisecs
De Linux est de 3000 (30 secondes) , et contrôle la durée avant l'expiration des données nouvellement écrites. (Voir https://lwn.net/Articles/322823/ ).
Voir https://www.kernel.org/doc/Documentation/sysctl/vm.txt pour des réglages plus liés, et google pour beaucoup plus. (par exemple, google sur dirty_writeback_centisecs
).
La valeur par défaut Linux pour /proc/sys/vm/dirty_writeback_centisecs
Est de 500 (5 secondes) , et PowerTop recommande de le définir sur 1500 (15 secondes) pour réduire la consommation d'énergie .
La réécriture différée donne également le temps au noyau de voir la taille d'un fichier avant de commencer à l'écrire sur le disque. Les systèmes de fichiers avec allocation retardée (comme XFS, et probablement d'autres de nos jours) ne choisissent même pas où sur le disque placer les données d'un fichier nouvellement écrit jusqu'à ce que cela soit nécessaire, séparément de l'allocation d'espace pour l'inode lui-même. Cela réduit la fragmentation en leur permettant d'éviter de placer le début d'un gros fichier dans un espace de 1 méga entre les autres fichiers, par exemple.
Si de nombreuses données sont en cours d'écriture, la réécriture sur le disque peut être déclenchée par un seuil pour la quantité de données sales (pas encore synchronisées sur le disque) pouvant se trouver dans le cache de page.
Si vous ne faites pas grand-chose d'autre, cependant, le voyant d'activité de votre disque dur ne s'allumera pas pendant 5 (ou 15) secondes après avoir appuyé sur Enregistrer sur un petit fichier.
Si votre éditeur a utilisé fsync()
après avoir écrit le fichier, le noyau l'écrira sur le disque sans délai. (Et fsync
ne reviendra pas tant que les données n'auront pas été réellement envoyées sur le disque).
Écriture de la mise en cache à l'intérieur le disque peut également être une chose, mais les disques essaient normalement de valider leur cache d'écriture dans le stockage permanent dès que possible, contrairement aux algorithmes de cache de page de Linux. Les caches d'écriture de disque sont plus un tampon de stockage pour absorber de petites rafales d'écritures, mais peut-être aussi pour retarder les écritures en faveur des lectures, et donner au micrologiciel des disques l'espace pour optimiser un modèle de recherche (par exemple, faites deux écritures ou lectures à proximité au lieu d'en faire une , puis chercher loin, puis chercher en arrière.)
Sur un disque rotatif (magnétique), vous pouvez voir quelques délais de recherche de 7 à 10 ms chacun avant que les données d'une commande d'écriture SATA ne soient réellement hors tension, s'il y avait des lectures/écritures en attente avant votre écriture. (Certaines autres réponses à cette question expliquent plus en détail les caches d'écriture de disque et les barrières d'écriture que les FS journalisés peuvent utiliser pour éviter la corruption.)