Quelle est la philosophie derrière le report de l'écriture de données sur disque?

72

Sous Linux, l’exécution d’une commande telle que cpou ddne signifie pas que les données ont été écrites sur le périphérique. Par exemple, vous devez appeler syncou appeler la fonction "Supprimer en toute sécurité" ou "Éjecter" sur le lecteur.

Quelle est la philosophie derrière une telle approche? Pourquoi les données ne sont-elles pas écrites en même temps? N'y a-t-il pas de risque d'échec de l'écriture à cause d'une erreur d'E / S?

Marmistrz
la source
16
N'oubliez pas que les appels système en lecture et en écriture peuvent fonctionner avec un octet à la fois, mais que les lecteurs de disque ne peuvent lire ou écrire que des blocs de taille fixe. La surcharge d'octet à la fois d'E / S serait intolérable sans mise en mémoire tampon. Avec la mise en mémoire tampon, c'est supportable.
Jonathan Leffler

Réponses:

47

Quelle est la philosophie derrière une telle approche?

Efficacité (meilleure utilisation des caractéristiques du disque) et performances (permettent à l'application de continuer immédiatement après une écriture).

Pourquoi les données ne sont-elles pas écrites en même temps?

Le principal avantage est que le système d'exploitation est libre de réorganiser et de fusionner des opérations d'écriture contiguës pour améliorer l'utilisation de la bande passante (moins d'opérations et moins de recherches). Les disques durs fonctionnent mieux lorsqu'un petit nombre d'opérations importantes sont demandées, alors que les applications nécessitent généralement un grand nombre d'opérations de petite taille. Une autre optimisation évidente est que le système d'exploitation peut également supprimer toutes les écritures sauf la dernière lorsque le même bloc est écrit plusieurs fois sur une courte période, ou même supprimer certaines écritures si le fichier affecté a été supprimé entre-temps.

Ces écritures asynchrones sont effectuées après le retour de l' writeappel système. C'est le deuxième et le plus visible avantage utilisateur. Les écritures asynchrones accélèrent les applications car elles sont libres de continuer leur travail sans attendre que les données soient réellement sur le disque. Le même type de mise en mémoire tampon / mise en cache est également mis en œuvre pour les opérations de lecture où des blocs récemment ou souvent lus sont conservés en mémoire au lieu d'être lus à nouveau sur le disque.

N'y a-t-il pas de risque d'échec de l'écriture à cause d'une erreur d'entrée-sortie?

Pas nécessairement. Cela dépend du système de fichiers utilisé et de la redondance en place. Une erreur d'E / S peut être sans danger si les données peuvent être sauvegardées ailleurs. Les systèmes de fichiers modernes tels que ZFS corrigent automatiquement les mauvais blocs de disque. Notez également que les erreurs d'E / S ne font pas planter les systèmes d'exploitation modernes. S'ils se produisent lors de l'accès aux données, ils sont simplement signalés à l'application concernée. S'ils se produisent lors de l'accès à des métadonnées structurelles et mettent le système de fichiers en péril, il peut être remonté en lecture seule ou rendu inaccessible.

Il existe également un léger risque de perte de données en cas de panne du système d'exploitation, de panne de courant ou de défaillance matérielle. C'est la raison pour laquelle les applications qui doivent être 100% sûres que les données sont sur disque (bases de données / applications financières, par exemple) font des écritures synchrones moins efficaces mais plus sécurisées. Pour limiter l'impact sur les performances, de nombreuses applications utilisent encore les écritures asynchrones mais les synchronisent éventuellement lorsque l'utilisateur enregistre explicitement un fichier (par exemple, vim, traitement de texte).

Par ailleurs, une très grande majorité des utilisateurs et des applications n’ont pas besoin de la sécurité que procurent les écritures synchrones. En cas d'accident ou de panne de courant, le seul risque est souvent de perdre au pire les 30 dernières secondes de données. À moins d'une transaction financière ou de quelque chose de similaire qui impliquerait un coût bien supérieur à 30 secondes, l'énorme gain de performance (qui n'est pas une illusion, mais bien réel), les écritures asynchrones permettent une surperformance substantielle du risque.

Enfin, les écritures synchrones ne suffisent pas pour protéger les données écrites. Si votre application a vraiment besoin de s’assurer que ses données ne peuvent pas être perdues quoi qu’il se produise, la réplication de données sur plusieurs disques et sur plusieurs emplacements géographiques doit être mise en place pour résister aux catastrophes telles que les incendies, les inondations, etc.

jlliagre
la source
En plus du coût, demandez-vous si quelque chose a été fait qui repose sur la sauvegarde des données. Si je tape dans mon roman en économisant de manière séquentielle, et qu'une coupure de courant signifie que je perds 30 secondes de travail, alors quelle que soit la valeur de ces 30 secondes au moins, je reviens à un état qui s'est réellement produit pendant le processus de dactylographie. , et je peux recommencer à partir de là. Par contre, si je clique sur «sauvegarder» puis que je fais rayer quelque chose de ma liste de tâches papier sur mon bureau, alors, lorsque je récupère, j’ai une incohérence entre mon disque dur et mon papier. Il est généralement plus difficile de résumer de ...
Steve Jessop
1
... donc, en tant qu'utilisateur normal, je souhaiterais peut-être synchroniser le système de fichiers avant de croiser "terminer l'écriture de mon roman" dans ma liste de tâches, afin de m'assurer que je ne pense pas avoir fait quelque chose qui échoue. Et c’est pourquoi les bases de données ont besoin d’écritures synchrones: même si elles perdent des données, elles doivent impérativement maintenir la cohérence.
Steve Jessop
1
@SteveJessop Je suis d'accord avec votre exemple, mais je ne m'attendrais pas à ce qu'un utilisateur occasionnel se synchronise manuellement. Si l'éditeur qui écrivait le précieux roman n'appelle pas fsync ou similaire lorsque le document est enregistré, il s'agit d'un bogue à corriger , par exemple: bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/817326 . J'utiliserais vi (vim) pour écrire le mien, vim appelle fsync à save par défaut.
jeudi
59

Cela donne simplement une illusion de vitesse aux programmes qui n'ont pas à attendre la fin de l'écriture. Montez vos systèmes de fichiers en mode synchronisation (ce qui vous donne vos écritures instantanées) et voyez à quel point tout est lent.

Parfois, les fichiers n'existent que temporairement ... un programme effectue un peu de travail et supprime le fichier juste après le travail. Si vous retardez ces écrits, vous pourriez vous en tirer en ne les ayant jamais écrits.

N'y a-t-il pas de risque d'échec de l'écriture à cause d'une erreur d'entrée-sortie?

Oh absolument. Dans un tel cas, généralement tout le système de fichiers passe en mode lecture seule, et tout est horrible. Mais cela arrive rarement, inutile de perdre les avantages en termes de performances en général.

Frostschutz
la source
Certains contrôleurs de disque dur ont une batterie de secours, ainsi, en cas de panne de courant, les données non validées sont conservées sur le contrôleur jusqu'à ce que le courant soit rétabli. Cela permet l'utilisation dans des applications de base de données où la perte de données n'est pas une option.
strattonn
Linux stocke les données non encore écrites dans la RAM, pas sur le disque dur. Le disque dur a aussi son propre cache.
Barafu Albino
Il serait très pratique que tout fichier ouvert par un processus soit synchronisé à la fermeture du processus. Cela n'affecterait pas le processus en lui-même, mais simplifierait les scripts shell et autres (qui doivent maintenant synchroniser tout un système de fichiers)
MSalters
14
C'est plus qu'une illusion. Les écritures asynchrones améliorent les performances globales des applications.
jlliagre
4
@frostschutz: Au-delà des fichiers qui n'existent que temporairement, il existe également le fait que certaines zones de fichiers sont ré-écrites à plusieurs reprises.
Matthieu M.
26

Des E / S asynchrones et mises en mémoire tampon étaient utilisées avant Linux et même avant Unix. Unix l'avait et toutes ses ramifications.

Voici ce que Ritchie et Thompson ont écrit dans leur document intitulé Le système de partage du temps UNIX :

Pour l'utilisateur, la lecture et l'écriture des fichiers semblent être synchrones et sans tampon. C'est après le retour d'un appel de lecture que les données sont disponibles et inversement, après une écriture, l'espace de travail de l'utilisateur peut être réutilisé. En fait, le système maintient un mécanisme de mise en mémoire tampon plutôt complexe qui réduit considérablement le nombre d'opérations d'E / S requises pour accéder à un fichier.


Dans votre question, vous avez également écrit:

N'y a-t-il pas de risque d'échec de l'écriture à cause d'une erreur d'entrée-sortie?

Oui, l'écriture peut échouer et le programme peut ne jamais le savoir. Bien que ce ne soit jamais une bonne chose, ses effets peuvent être minimisés dans les cas où une erreur d'E / S génère un panique système (sur certains OS, cela est configurable. Au lieu de paniquer, le système peut continuer à s'exécuter mais le système de fichiers affecté est non monté ou monté en lecture seule). Les utilisateurs peuvent ensuite être avertis que les données de ce système de fichiers sont suspectes. Et un lecteur de disque peut être surveillé de manière proactive pour voir si sa liste de défauts développés augmente rapidement, ce qui indique que le lecteur est en panne.

BSD a ajouté l' fsyncappel système afin qu'un programme puisse être certain que ses données de fichier avaient été complètement écrites sur disque avant de poursuivre, et les systèmes Unix suivants ont fourni des options pour effectuer des écritures synchrones. GNU dd dispose d’une option conv=fsyncpermettant de s’assurer que toutes les données ont été écrites avant la fermeture de la commande. Il est pratique lors de l'écriture pour ralentir les lecteurs flash amovibles, où l'écriture des données en mémoire tampon peut prendre plusieurs minutes.

Un arrêt soudain du système, causé par exemple par une panne de courant, est une autre source de corruption des fichiers. Pratiquement tous les systèmes actuels prennent en charge un indicateur clean / dirty dans leurs systèmes de fichiers. L'indicateur est défini sur clean lorsqu'il n'y a plus de données à écrire et que le système de fichiers est sur le point d'être démonté, généralement pendant l'arrêt du système ou par un appel manuel umount. Les systèmes s’exécutent généralement fsckau redémarrage s’ils détectent que les systèmes de fichiers n’ont pas été arrêtés proprement.

Mark Plotnick
la source
Supposons que nous copions de la musique d’un disque dur sur un lecteur externe. Il peut arriver que le lecteur externe soit corrompu et que l'écriture échoue. Cela ne provoquerait pas l'exécution d'un programme avec des données erronées. Et il semble exagéré de paniquer après un échec d'entrée / sortie sur un périphérique externe.
Marmistrz
Bon point. Je vais modifier ma réponse.
Mark Plotnick
15

Beaucoup de bonnes réponses, mais permettez-moi d'ajouter une chose… Rappelez-vous qu'Unix est un système multi-processus et multi-utilisateurs, de sorte que de nombreux utilisateurs pourraient potentiellement essayer de faire des opérations sur les fichiers (en particulier des écritures) à (presque) la en même temps. Avec d'anciens disques durs lents - peut-être montés sur le réseau - cela prendrait non seulement du temps (pour lequel les programmes se verrouillaient en principe et les utilisateurs devaient attendre), mais aussi beaucoup de déplacement de la tête de lecture / écriture du lecteur. disque en arrière.

Au lieu de cela, les fichiers en attente d'écriture ont été conservés en mémoire pendant un certain temps, puis triés après l'endroit où ils devaient se retrouver sur le disque ... et lorsque le tampon était saturé - ou que le démon de synchronisation du disque avait attendu la fin. nombre de secondes requis (généralement environ 30 secondes, je pense) - la totalité de la mémoire tampon a été écrite sur le disque "dans l’ordre", la tête d’écriture devant uniquement effectuer un mouvement de balayage continu, en écrivant les fichiers sur le disque en tant que ça s'est passé ... au lieu de sauter partout.

Bien sûr, avec les disques rapides actuels - sans parler des périphériques à semi-conducteurs - le gain est beaucoup moins… surtout sur un système Linux à la maison, où un seul utilisateur travaille à la fois, et avec seulement quelques programmes.

Quoi qu'il en soit, anticiper les lectures en lisant (dans le cache / tampon) plus que ce qui était demandé - et trier les données en attente d'écriture afin qu'elles puissent être écrites en "un seul mouvement" - était en fait une très bonne idée au début. le temps, en particulier sur les systèmes avec beaucoup de lecture et d'écriture par de nombreux utilisateurs.

Baard Kopperud
la source
2
XFS ne décide même pas où mettre les données avant l'écriture. L'allocation différée donne à l'allocateur beaucoup plus d'informations sur lesquelles baser ses décisions. Lorsqu'un fichier est écrit pour la première fois, il est impossible de savoir s'il s'agira d'un fichier 4k ou d'un fichier 1G et toujours en croissance. S'il y a 10G d'espace libre contigu quelque part, placer le fichier 4k au début ne sert à rien. Placer le fichier volumineux au début d’un grand espace libre réduit la fragmentation.
Peter Cordes
13

Il n’est pas spécifique à Linux, il s’appelle le cache de pages (que Linux fait très bien). Voir aussi http://linuxatemyram.com/ ; ainsi, si un fichier est écrit, puis relu quelques secondes plus tard, très souvent, aucune E / S disque n'est nécessaire.

Le principal avantage est que sur de nombreux systèmes, il y a beaucoup de RAM, et une partie de celle-ci peut être utilisée comme cache par le noyau. Ainsi, certaines opérations sur les fichiers peuvent tirer profit de cette mise en cache. En outre, la durée des E / S de disque est beaucoup plus lente (généralement plusieurs milliers de fois pour SDD et presque un million de fois pour les disques durs mécaniques) par rapport à la RAM.

Le code de l'application peut donner des indications sur cette mise en cache: voir par exemple posix_fadvise (2) & madvise (2)

Basile Starynkevitch
la source
8

Les plateaux tournants sont plus lents que la RAM. Nous utilisons la mise en cache des lectures / écritures pour "masquer" ce fait.

La chose utile à propos de l’écriture IO est qu’elle n’exige pas que l’E / S de disque se produise immédiatement, contrairement à une lecture, dans laquelle vous ne pouvez pas renvoyer de données à l’utilisateur tant que la lecture n’est pas terminée sur le disque.

Ainsi, les écritures fonctionnent sous une contrainte temporelle souple - tant que notre débit soutenu ne dépasse pas celui de notre disque, nous pouvons masquer une grande partie des inconvénients liés aux performances dans un cache d'écriture.

Et nous avons besoin d'écrire en cache - les disques en rotation sont relativement lents comparativement. Mais ainsi, les types de RAID modernes ont une pénalité importante en termes de fonctionnement.

Un RAID 6 par exemple, pour terminer une entrée / sortie en écriture, il faut:

  • Lire le bloc de mise à jour
  • lire la parité1
  • lire la parité 2
  • écrire un nouveau bloc
  • écrire la parité 1
  • écrire la parité 2

Ainsi, chaque écriture correspond à 6 opérations d'E / S. En particulier, lorsque vous utilisez des disques lents, tels que de gros disques SATA, cela devient extrêmement coûteux.

Mais il existe une solution simple et agréable: écrivez en coalescence. Si vous pouvez créer une écriture «en bande complète» dans une mémoire tampon, vous n'avez pas besoin de lire la parité à partir de votre disque. Vous pouvez la calculer en fonction de ce que vous avez en mémoire.

C'est très souhaitable, car vous n'avez plus d'amplification en écriture. En effet, vous pouvez vous retrouver avec une pénalité en écriture plus faible que RAID 1 + 0.

Considérer:

RAID 6, 8 + 2 - 10 broches.

8 blocs de données consécutifs à écrire - calculez la parité dans le cache et écrivez un bloc sur chaque disque. 10 écritures par 8, signifie une pénalité en écriture de 1,25. 10 disques de RAID 1 + 0 ont toujours une pénalité en écriture de 2 (car vous devez écrire sur chaque sous-miroir). Dans ce scénario, vous pouvez donc améliorer les performances de RAID 6 par rapport à RAID1 + 0. Dans le monde réel, vous obtenez cependant un peu plus d'un profil d'E / S mixte.

La mise en cache d'écriture a donc une grande incidence sur les performances perçues des ensembles RAID: vous pouvez écrire à la vitesse de la mémoire vive et subir une pénalité d'écriture faible, ce qui améliore votre débit soutenu si vous le faites.

Et si vous ne le faites pas, vous souffrez de la lenteur des performances de SATA, mais multipliez-le par 6 et ajoutez un peu de controverse. Votre SATA RAID-6 à 10 voies sans la mise en cache en écriture serait un peu plus rapide qu’un seul lecteur sans RAID ... mais pas de beaucoup.

Comme vous le constatez, vous prenez un risque, mais une panne de courant signifie une perte de données. Vous pouvez résoudre ce problème en effectuant des cycles de vidage du cache, en sauvegardant la batterie sur votre cache ou en utilisant un disque SSD ou un autre cache non volatile.

Sobrique
la source
7

Aucune des autres réponses ne mentionnait une allocation différée . XFS, ext4, BTRFS et ZFS l'utilisent tous. XFS l'utilisait depuis qu'ext4 existait déjà, je vais donc l'utiliser comme exemple:

XFS ne décide même pas où mettre les données avant l'écriture. L'allocation différée donne à l'allocateur beaucoup plus d'informations sur lesquelles baser ses décisions. Lorsqu'un fichier est écrit pour la première fois, il est impossible de savoir s'il s'agira d'un fichier 4k ou d'un fichier 1G et toujours en croissance. S'il y a 10G d'espace libre contigu quelque part, placer le fichier 4k au début ne sert à rien. Placer le fichier volumineux au début d’un grand espace libre réduit la fragmentation.

Peter Cordes
la source
4

Toutes les autres réponses ici sont pour le moins presque toutes correctes pour le cas normal, et je vous recommanderais d'en lire une avant le mien, mais vous avez mentionné que dd et dd ont un cas d'utilisation typique qui peut ne pas impliquer la mise en cache d'écriture. La mise en cache en écriture est principalement mise en œuvre au niveau du système de fichiers. Les périphériques bruts ne font normalement pas la mise en cache en écriture (plusieurs pilotes de périphérique tels que raid ou lvm sont une autre boule de cire). Étant donné que dd est souvent utilisé avec des périphériques en mode bloc, il fournit le bs et les options associées afin de permettre des écritures volumineuses pour de meilleures performances sur les périphériques bruts. Cela n’est pas aussi utile lorsque les deux ordinateurs d'extrémité sont des fichiers normaux (bien que les écritures volumineuses utilisent moins d'appels système dans ce cas). L'autre endroit commun où cela est particulièrement visible est le paquetage mtools, qui est une implémentation du système de fichiers fat de l'espace utilisateur. utiliser mtools avec un lecteur de disquette est toujours incroyablement lent, car les outils sont complètement synchrones et les lecteurs de disquettes sont incroyablement lents. Monter la disquette et utiliser le système de fichiers fat du noyau est beaucoup plus réactif, sauf pour umount qui est synchrone (et très important pour éviter les pertes de données, en particulier pour les périphériques amovibles tels que les disquettes). Je ne suis au courant que de quelques autres programmes utilisés régulièrement avec des périphériques bruts tels que des bases de données spécialement configurées (qui implémentent leur propre cache d'écriture), tar et des périphériques et outils de système de fichiers spécialisés tels que chdsk, mkfs et mt. Monter la disquette et utiliser le système de fichiers fat du noyau est beaucoup plus réactif, sauf pour umount qui est synchrone (et très important pour éviter les pertes de données, en particulier pour les périphériques amovibles tels que les disquettes). Je ne suis au courant que de quelques autres programmes utilisés régulièrement avec des périphériques bruts tels que des bases de données spécialement configurées (qui implémentent leur propre cache d'écriture), tar et des périphériques et outils de système de fichiers spécialisés tels que chdsk, mkfs et mt. Monter la disquette et utiliser le système de fichiers fat du noyau est beaucoup plus réactif, sauf pour umount qui est synchrone (et très important pour éviter les pertes de données, en particulier pour les périphériques amovibles tels que les disquettes). Je ne suis au courant que de quelques autres programmes utilisés régulièrement avec des périphériques bruts tels que des bases de données spécialement configurées (qui implémentent leur propre cache d'écriture), tar et des périphériques et outils de système de fichiers spécialisés tels que chdsk, mkfs et mt.

Hildred
la source
4
Les périphériques de bloc Linux lisent / écrivent le cache de page par défaut. Vous devez utiliser O_DIRECTsi vous voulez contourner le cache. dd oflag=direct. IIRC, certains ordinateurs par défaut pour diriger les E / S directes sur les périphériques en mode bloc. (Et requièrent la lecture / écriture de blocs alignés, ce que Linux ne fait pas, car il écrit de toute façon le pagecache.)
Peter Cordes
3

La philosophie est non sécurisée par défaut.

Deux stratégies raisonnables et évidentes sont possibles: écrire immédiatement sur le disque ou écrire en différé. UNIX a historiquement choisi ce dernier. Donc, pour la sécurité, vous devez appeler fsyncaprès.

Cependant, vous pouvez spécifier la sécurité dès le départ en montant un périphérique avec une option syncou par fichier en l'ouvrant avec O_SYNC.

N'oubliez pas qu'UNIX a été conçu pour les experts en informatique. "Safe by default" n'était pas une considération. La sécurité signifie des E / S plus lentes, et ces premiers systèmes avaient vraiment des E / S lentes, ce qui rendait le prix élevé. Malheureusement, ni UNIX ni Linux ne sont passés à safe-be-default, même s’il s’agit d’un changement incessant.

MSalters
la source
6
Une très grande majorité des applications et des utilisateurs n’ont pas besoin de la sécurité que procurent les écritures synchrones, ni ne s’y intéressent. En cas d'accident ou de panne de courant, vous risquez de perdre jusqu'à 30 secondes de données. Cela convient à la plupart des gens, sauf s’il s’agit d’une transaction financière ou de quelque chose de similaire qui coûtera plus de 30 secondes de notre temps. Le réglage par défaut sur les E / S synchrones aurait impliqué toutes les applications ciblant l'utilisabilité pour définir O_NOSYNC.
Juillet
2

Il échange une faible quantité de fiabilité pour une augmentation importante du débit.

Supposons, par exemple, un programme de compression vidéo. Avec écriture différée ("write back"):

  1. passer 10ms à compresser le cadre
  2. émettre le cadre d'écriture sur le disque
  3. attendez 10ms pour que le disque reconnaisse que l'écriture est terminée
  4. GOTO 1

Contre

  1. passer 10ms à compresser le cadre
  2. édition du cadre d'écriture sur le disque (se termine en arrière-plan)
  3. GOTO 1

La deuxième version apparaît deux fois plus vite car elle peut utiliser simultanément le processeur et le disque, alors que la première version attend toujours l'une ou l'autre.

En règle générale, vous souhaitez réécrire pour les opérations de streaming et les opérations de fichiers en bloc, et l'écriture directe pour les bases de données et les applications similaires.

pjc50
la source
1

Dans de nombreuses applications, les périphériques de stockage seront occupés à lire des données par intermittence. Si un système est toujours en mesure de différer les écritures jusqu'au moment où le périphérique de stockage n'est pas occupé à lire des données, du point de vue de l'application, les écritures ne prendront aucun temps. Les seules situations dans lesquelles l'écriture ne serait pas instantanée seraient les suivantes:

  1. Les tampons d'écriture se remplissent à un point tel qu'aucune autre demande d'écriture différée ne peut être acceptée avant la fin des écritures.

  2. Il est nécessaire d'éteindre ou de supprimer le périphérique pour lequel des écritures sont en attente.

  3. Une application demande spécifiquement la confirmation qu'une écriture est réellement terminée.

En effet, c’est uniquement en raison des exigences susmentionnées que l’écriture doit avoir lieu. D'un autre côté, il n'y a généralement aucune raison de ne pas effectuer d'écriture en attente à des moments où un périphérique serait autrement inactif. Par conséquent, de nombreux systèmes les exécutent.

supercat
la source
0

Il y a aussi ceci:

Écrire "Salut, Joe Moe"
est plus rapide que:
Écrire "Salut,"
Écrire "Joe"
Écrire "Moe"

Et aussi:

Ecris "Salut, comment vas-tu?"
est plus rapide que:
Ecrire "Salut, quoi de neuf?"
Supprimer cette
écriture "Salut, comment vas-tu?"
Supprimer cette
écriture "Salut, comment vas-tu?"

Il est préférable que les modifications et l'agrégation se produisent dans la RAM que sur le disque. Le traitement par lots d'écriture sur disque libère les développeurs d'applications de ces problèmes.

Rolf
la source