Kiedyś myślałem, że zmiany plików są zapisywane bezpośrednio na dysku, to znaczy, jak tylko zamykam plik i decyduję się kliknąć / wybrać zapisać. Jednak w ostatniej rozmowie mój przyjaciel powiedział mi, że to zwykle nie jest prawda; system operacyjny (konkretnie mówiliśmy o systemach Linux) zachowuje zmiany w pamięci i ma demona, który faktycznie zapisuje zawartość z pamięci na dysk.
Podał nawet przykład zewnętrznych dysków flash: są one montowane w systemie (kopiowane do pamięci), a czasami dochodzi do utraty danych, ponieważ demon nie zapisał jeszcze zawartości w pamięci flash; dlatego odmontowujemy dyski flash.
Nie mam wiedzy na temat funkcjonowania systemów operacyjnych, więc nie mam absolutnie pojęcia, czy to prawda i w jakich okolicznościach. Moje główne pytanie brzmi: czy dzieje się tak, jak opisano w systemach Linux / Unix (i może w innych systemach operacyjnych)? Czy na przykład oznacza to, że jeśli wyłączę komputer natychmiast po edycji i zapisaniu pliku, moje zmiany najprawdopodobniej zostaną utracone? Być może zależy to od typu dysku - tradycyjnych dysków twardych vs. dysków półprzewodnikowych?
Pytanie dotyczy w szczególności systemów plików, które mają dysk do przechowywania informacji, nawet jeśli wszelkie wyjaśnienia lub porównania są dobrze odbierane.
źródło
sync
, a aplikacje musząflush
zagwarantować, że pamięci podręczne zostaną zapisane, ale nawet sukcessync
nie gwarantuje zapisu na dysk fizyczny, tylko że pamięci podręczne jądra są opróżniane na dysk, co może mieć opóźnienie w sterowniku lub sprzęcie dyskowym (np. utraconej pamięci podręcznej na dysku)Odpowiedzi:
Oni mogą być. Nie powiedziałbym „najprawdopodobniej”, ale prawdopodobieństwo zależy od wielu rzeczy.
Łatwym sposobem na zwiększenie wydajności zapisywania plików jest to, że system operacyjny po prostu buforuje dane, mówi (kłamie) aplikacji, przez którą przeszedł zapis, a następnie faktycznie zapisuje później. Jest to szczególnie przydatne, jeśli jednocześnie odbywa się inna aktywność na dysku: system operacyjny może nadawać priorytet odczytom i zapisywać później. Może także całkowicie wyeliminować potrzebę rzeczywistego zapisu, np. W przypadku szybkiego usunięcia pliku tymczasowego.
Problem buforowania jest bardziej wyraźny, jeśli pamięć jest wolna. Kopiowanie plików z szybkiego dysku SSD na wolną pamięć USB prawdopodobnie będzie wymagało dużo buforowania zapisu, ponieważ pamięć USB po prostu nie nadąża. Ale twoje
cp
polecenie powraca szybciej, więc możesz kontynuować pracę, być może nawet edytować pliki, które właśnie zostały skopiowane.Oczywiście takie buforowanie ma tę wadę, że niektóre dane mogą zostać utracone, zanim zostaną faktycznie zapisane. Użytkownik zostanie zmiażdżony, jeśli jego redaktor poinformuje go, że zapis się powiódł, ale plik nie znajdował się na dysku. Dlatego istnieje
fsync()
wywołanie systemowe , które ma powrócić dopiero po tym, jak plik rzeczywiście trafi na dysk. Twój edytor może to wykorzystać, aby upewnić się, że dane są poprawne, zanim zgłosi użytkownikowi, że zapis się powiódł.Powiedziałem „powinien”, ponieważ sam dysk może powiedzieć systemowi te same kłamstwa i powiedzieć, że zapis został zakończony, podczas gdy plik naprawdę istnieje tylko w niestabilnej pamięci podręcznej zapisu na dysku. W zależności od napędu może nie być tego możliwe.
Oprócz
fsync()
tego istnieją również wywołaniasync()
isyncfs()
systemowe, które proszą system o upewnienie się, że wszystkie zapisy w całym systemie lub wszystkie zapisy w określonym systemie plików trafiły na dysk. Dosync
wywołania tych narzędzi można użyć narzędzia .Jest też
O_DIRECT
flaga doopen()
, która ma „próbować zminimalizować efekty bufora we / wy do iz tego pliku”. Usunięcie buforowania zmniejsza wydajność, więc jest to najczęściej używane przez aplikacje (bazy danych), które wykonują własne buforowanie i chcą mieć nad nim kontrolę. (O_DIRECT
nie jest bez problemów, komentarze na ten temat na stronie podręcznika są nieco zabawne).To, co dzieje się po wyłączeniu zasilania, zależy również od systemu plików. Powinieneś martwić się nie tylko danymi o plikach, ale także metadanymi systemu plików. Posiadanie danych pliku na dysku jest mało przydatne, jeśli nie możesz go znaleźć. Po prostu rozszerzenie pliku do większego rozmiaru wymaga przydzielenia nowych bloków danych i należy je gdzieś oznaczyć.
Sposób, w jaki system plików radzi sobie ze zmianami metadanych i kolejność między metadanymi a zapisami danych, jest bardzo różna. Np.
ext4
Jeśli ustawisz flagę mountdata=journal
, wówczas wszystkie zapisy - nawet zapisy danych - przechodzą przez dziennik i powinny być raczej bezpieczne. Oznacza to również, że są pisane dwukrotnie, więc wydajność spada. Domyślne opcje próbują uporządkować zapisy, aby dane znajdowały się na dysku przed zaktualizowaniem metadanych. Inne opcje lub inny system plików mogą być lepsze lub gorsze; Nie będę nawet próbować kompleksowego badania.W praktyce w słabo załadowanym systemie plik powinien trafić na dysk w ciągu kilku sekund. Jeśli masz do czynienia z pamięcią wymienną, odinstaluj system plików przed wyciągnięciem nośnika, aby upewnić się, że dane są faktycznie wysyłane na dysk, i że nie będzie żadnej dalszej aktywności. (Lub niech środowisko GUI zrobi to za Ciebie).
źródło
some cases where
link nie wydaje się mówić o takich przypadkach - zamiast tego mówi, że były problemy, gdy aplikacje nie korzystałyfsync
. Czy powinienem przejrzeć komentarze, aby znaleźć przypadki, na które wskazujesz?sync
bezpośrednio jako polecenia powłoki systemowej, aby naciągnąć jądro i opróżnić wszystkie pamięci podręczne.fsync()
po zapisaniu pliku. Domyślne ustawienie Linuksa/proc/sys/vm/dirty_writeback_centisecs
to 500 (5 sekund), a PowerTop zaleca ustawienie go na 1500 (15 sekund). ( kernel.org/doc/Documentation/sysctl/vm.txt ). W lekko obciążonym systemie jądro po prostu pozwoli mu pozostać brudne w pamięci podręcznej strony na długowrite()
przed opróżnieniem na dysk, aby zoptymalizować przypadek, w którym zostanie wkrótce usunięty lub zmodyfikowany.Istnieje niezwykle prosty sposób, aby udowodnić, że nie może być prawdą, że zmiany plików są zawsze zapisywane bezpośrednio na dysku, a mianowicie fakt, że istnieją systemy plików, które nie są wspierane przez dysk w pierwszej kolejności . Jeśli system plików nie ma dysku w pierwszej kolejności, to nie może ewentualnie zapisać zmiany na dysku, kiedykolwiek .
Oto niektóre przykłady:
tmpfs
, system plików, który istnieje tylko w pamięci RAM (a ściślej w buforze pamięci podręcznej)ramfs
, system plików, który istnieje tylko w pamięci RAMsysfs
,procfs
,devfs
,shmfs
, ...)Ale nawet w przypadku systemów plików z dyskami jest to zwykle nieprawda. Strona „ Jak zepsuć bazę danych SQLite” zawiera rozdział „ Synchronizacja synchronizacji”, który opisuje wiele różnych sposobów zapisywania (w tym przypadku zatwierdzania bazy danych SQLite) na dysku. SQLite ma również białą księgę wyjaśniającą wiele obręczów, przez które trzeba przeskoczyć, aby zagwarantować Atomic Commit In SQLite . (Zauważ, że Zapis Atomowy jest o wiele trudniejszy niż tylko Zapis , ale oczywiście zapis na dysk jest podproblemem zapisu Atomowego i możesz się wiele dowiedzieć o tym problemie z tego artykułu.) Ten artykuł zawiera sekcja na temat rzeczy, które mogą pójść nie tak, która zawiera podrozdział na tematNiekompletne opróżnianie dysku, które podaje kilka przykładów subtelnych zawiłości, które mogą uniemożliwić dotarcie zapisu na dysk (np. Kontroler HDD zgłasza, że zapisał na dysk, gdy tak naprawdę nie ma - tak, są producenci dysków twardych, którzy to robią, i może nawet być zgodne z prawem zgodnie ze specyfikacją ATA, ponieważ jest niejednoznacznie sformułowane w tym względzie).
źródło
Prawdą jest, że większość systemów operacyjnych, w tym Unix, Linux i Windows, używa pamięci podręcznej zapisu w celu przyspieszenia operacji. Oznacza to, że wyłączenie komputera bez wyłączania go jest złym pomysłem i może prowadzić do utraty danych. To samo dotyczy, jeśli usuniesz pamięć USB, zanim będzie ona gotowa do usunięcia.
Większość systemów oferuje również opcję synchronizacji zapisów. Oznacza to, że dane będą na dysku, zanim aplikacja otrzyma potwierdzenie sukcesu, kosztem spowolnienia.
Krótko mówiąc, istnieje powód, dla którego należy poprawnie zamknąć komputer i odpowiednio przygotować pamięć USB do usunięcia.
źródło
fsync()
syscall z programu. Z poziomu powłoki wystarczy użyćsync
polecenia.sync
został zaimplementowany jako brak operacji . Nawet w przypadku systemów plików, które poprawnie się implementująsync
, nadal występuje problem, że niektóre oprogramowanie układowe dysku wdrażająFLUSH CACHE
jako brak działania lub natychmiast wracają z niego i wykonują go w tle.1. Pamięć flash
Gdy masz wybór, nie powinieneś pozwolić, aby pamięć flash przestała działać bez czystego wyłączenia.
W przypadku taniego magazynu, takiego jak karty SD, można spodziewać się utraty całych bloków wymazywania (kilka razy większych niż 4KB), utraty danych, które mogłyby należeć do różnych plików lub istotnych struktur systemu plików.
Niektóre drogie dyski SSD mogą twierdzić, że oferują lepsze gwarancje w przypadku awarii zasilania. Jednak testy innych firm sugerują, że wiele drogich dysków SSD tego nie robi. Warstwa, która ponownie mapuje bloki w celu „wyrównywania zużycia”, jest złożona i zastrzeżona. Możliwe awarie obejmują utratę wszystkich danych na dysku.
2017: https://dl.acm.org/citation.cfm?id=2992782&preflayout=flat
2013: https://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf?wptouch_preview_theme=enabled
2. Wirujące dyski twarde
Wirujące dyski twarde mają różne właściwości. Ze względów bezpieczeństwa i prostoty zalecam założenie, że mają one taką samą praktyczną niepewność jak pamięć flash.
Chyba że masz konkretne dowody, których wyraźnie nie masz. Nie mam danych porównawczych dotyczących obracania dysków twardych.
Dysk twardy może pozostawić jeden niekompletnie zapisany sektor ze złą sumą kontrolną, co w późniejszym czasie spowoduje błąd odczytu. Ogólnie mówiąc, ten tryb awarii dysków twardych jest całkowicie oczekiwany; natywne systemy plików Linux zostały zaprojektowane z myślą o tym. Mają one na celu zachowanie kontraktu
fsync()
w obliczu tego rodzaju awarii zasilania. (Naprawdę chcielibyśmy, aby gwarantowano to na dyskach SSD).Jednak nie jestem pewien, czy systemy plików Linux osiągają to we wszystkich przypadkach, czy też jest to w ogóle możliwe.
Następny rozruch po tym typie błędu może wymagać naprawy systemu plików. W systemie Linux możliwe jest, że naprawa systemu plików zada kilka pytań, których nie rozumiesz, gdzie możesz nacisnąć tylko Y i mieć nadzieję, że to się rozwiąże.
2.1 Jeśli nie wiesz, czym jest umowa fsync ()
Umowa fsync () jest źródłem zarówno dobrych, jak i złych wiadomości. Najpierw musisz zrozumieć dobre wieści.
Dobra wiadomość:
fsync()
jest dobrze udokumentowana jako poprawny sposób zapisywania danych pliku, np. Po naciśnięciu przycisku „zapisz”. I jest szeroko rozumiane, że np. Edytory tekstu muszą zamieniać istniejące pliki za pomocą atomurename()
. Ma to na celu upewnienie się, że zawsze zachowujesz stary plik lub otrzymujesz nowy plik (który byłfsync()
edytowany przed zmianą nazwy). Nie chcesz pozostać z częściowo zapisaną wersją nowego pliku.Zła wiadomość: przez wiele lat wywołanie fsync () w najpopularniejszym systemie plików Linuxa mogło skutecznie zawiesić cały system na dziesiątki sekund. Ponieważ aplikacje nie mogą nic na to poradzić, bardzo często optymistycznie używa się rename () bez fsync (), co wydaje się względnie niezawodne w tym systemie plików.
Dlatego istnieją aplikacje, które nie używają poprawnie fsync ().
Następna wersja tego systemu plików na ogół unikała zawieszenia fsync () - w tym samym czasie, gdy zaczęła polegać na prawidłowym użyciu fsync ().
To wszystko jest całkiem złe. Zrozumienia tej historii prawdopodobnie nie pomaga lekceważący ton i inwolucja, z której korzystało wielu sprzecznych twórców jądra.
Obecna rozdzielczość to obecny najpopularniejszy system plików Linux
domyślnie obsługuje wzorzec rename () bez wymagania fsync ()implementuje „kompatybilność błędów dla błędów” z poprzednią wersją. Można to wyłączyć za pomocą opcji montowanianoauto_da_alloc
.To nie jest pełna ochrona. Zasadniczo opróżnia oczekujące operacje we / wy w czasie zmiany nazwy (), ale nie czeka na zakończenie operacji we / wy przed zmianą nazwy. Jest to jednak znacznie lepsze niż np. 60-sekundowe okno zagrożenia! Zobacz także odpowiedź na Które systemy plików wymagają fsync () w celu zapewnienia bezpieczeństwa w razie awarii podczas zamiany istniejącego pliku na rename ()?
Niektóre mniej popularne systemy plików nie zapewniają ochrony. XFS odmawia tego. I UBIFS nie wdrożył go albo, widocznie to może być zaakceptowane, ale wymaga dużo pracy, aby to możliwe. Ta sama strona wskazuje, że UBIFS ma kilka innych problemów „TODO” w zakresie integralności danych, w tym utraty zasilania. UBIFS to system plików używany bezpośrednio w pamięci flash. Wyobrażam sobie, że niektóre trudności, o których wspomina UBIFS z pamięcią flash, mogą być związane z błędami SSD.
źródło
W słabo załadowanym systemie jądro pozwoli nowo zapisanym danym plikowym pozostać w pamięci podręcznej strony przez około 30 sekund po, a
write()
następnie opróżnić je na dysk, aby zoptymalizować pod kątem przypadku, gdy zostaną wkrótce usunięte lub zmodyfikowane.dirty_expire_centisecs
Domyślne ustawienie Linuksa to 3000 (30 sekund) i kontroluje, ile czasu minie, zanim nowo zapisane dane „wygasną”. (Zobacz https://lwn.net/Articles/322823/ ).Zobacz https://www.kernel.org/doc/Documentation/sysctl/vm.txt, aby uzyskać więcej powiązanych tuneli, a Google, aby uzyskać wiele innych. (np. google on
dirty_writeback_centisecs
).Domyślne ustawienie Linuksa
/proc/sys/vm/dirty_writeback_centisecs
to 500 (5 sekund) , a PowerTop zaleca ustawienie go na 1500 (15 sekund) w celu zmniejszenia zużycia energii.Opóźnione zapisywanie daje jądrze czas na sprawdzenie, jak duży będzie plik, zanim zacznie zapisywać go na dysk. Systemy plików z opóźnionym przydziałem (takie jak XFS i prawdopodobnie inne obecnie) nawet nie wybierają miejsca na dysku, aby umieścić dane nowo zapisanego pliku, dopóki nie jest to konieczne, niezależnie od przydzielania miejsca dla samego i-węzła. Zmniejsza to fragmentację, pozwalając im na przykład uniknąć umieszczenia początku dużego pliku w odległości 1 megapiksela między innymi plikami.
W przypadku zapisywania dużej ilości danych, zapis na dysk może zostać uruchomiony przez próg określający, ile brudnych (jeszcze nie zsynchronizowanych z dyskiem) danych może znajdować się w pamięci podręcznej.
Jeśli jednak nie robisz nic więcej, lampka aktywności dysku twardego nie będzie świecić przez 5 (lub 15) sekund po naciśnięciu przycisku Zapisz na małym pliku.
Jeśli twój edytor używał
fsync()
po zapisaniu pliku, jądro bezzwłocznie zapisze go na dysku. (Ifsync
nie powróci, dopóki dane nie zostaną faktycznie przesłane na dysk).Buforowanie zapisu w obrębie dysku może być również rzecz, ale dyski zazwyczaj próbują popełnić ich zapisu-cache do stałego przechowywania ASAP, w przeciwieństwie do algorytmów strona-cache Linuksa. Pamięci podręczne zapisu na dysku są bardziej buforem do przechowywania, aby wchłonąć małe ilości zapisów, ale może również opóźnić zapisy na korzyść odczytów i dać oprogramowaniu dyskowemu miejsce na zoptymalizowanie wzorca wyszukiwania (np. Wykonaj dwa zapisy lub odczyty w pobliżu zamiast wykonać jeden , następnie szukając daleko, a następnie szukając wstecz).
Na obracającym się (magnetycznym) dysku może wystąpić kilka opóźnień wyszukiwania wynoszących od 7 do 10 ms każdy, zanim dane z polecenia zapisu SATA będą faktycznie bezpieczne przed wyłączeniem, jeśli przed zapisaniem były oczekujące odczyty / zapisy. (Niektóre inne odpowiedzi na to pytanie zawierają bardziej szczegółowe informacje na temat pamięci podręcznych zapisu na dyskach i barier zapisu, które mogą być używane przez FS w dziennikach, aby uniknąć uszkodzenia).
źródło