Czy edycje plików w systemie Linux są zapisywane bezpośrednio na dysku?

57

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.

JuanRocamonde
źródło
8
FAO: Zamknij Głosuj recenzentów kolejek. To nie jest prośba o materiały do ​​nauki. Zobacz unix.meta.stackexchange.com/q/3892/22812
Anthony G - Sprawiedliwość dla Moniki
2
Pamięć podręczna jest nieprzezroczysta dla użytkownika, w najlepszym przypadku jest to konieczne sync, a aplikacje muszą flushzagwarantować, że pamięci podręczne zostaną zapisane, ale nawet sukces syncnie 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)
crasic
1
Chociaż nie zgadzam się z tym, że jest to prośba o materiały do ​​nauki, myślę, że pytanie jest nieco ogólne w obecnej formie. Ogranicz zakres do dystrybucji Linuksa (lub dowolnego innego systemu operacyjnego) i ewentualnie ogranicz go do niektórych technologii przechowywania i systemów plików.
Jeff Schaller
3
Jak zauważył @AnthonyGeoghegan, nie uważam tego pytania za prośbę o materiały edukacyjne. Myślę, że to raczej specyficzne; Nie prosiłem o długie i głębokie wyjaśnienie lub instrukcję dotyczącą systemów plików Linux; tylko krótki pomysł, który chciałem wyjaśnić.
JuanRocamonde
3
To prawda, że ​​może być nieco szeroki, @JeffSchaller; Spróbuję go trochę edytować; Jednak szczerze mówiąc, jeśli strona nie jest przeznaczona dla tego rodzaju pytań, które bezpośrednio dotyczą funkcjonowania Linuksa, to po co to jest?
JuanRocamonde

Odpowiedzi:

70

czy wyłączę komputer natychmiast po edycji i zapisaniu pliku, moje zmiany najprawdopodobniej zostaną utracone?

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 cppolecenie 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łania sync()i syncfs()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. Do syncwywołania tych narzędzi można użyć narzędzia .

Jest też O_DIRECTflaga 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_DIRECTnie 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. ext4Jeśli ustawisz flagę mount data=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).

ilkkachu
źródło
Twój some cases wherelink nie wydaje się mówić o takich przypadkach - zamiast tego mówi, że były problemy, gdy aplikacje nie korzystały fsync. Czy powinienem przejrzeć komentarze, aby znaleźć przypadki, na które wskazujesz?
Ruslan
1
Możesz także użyć syncbezpośrednio jako polecenia powłoki systemowej, aby naciągnąć jądro i opróżnić wszystkie pamięci podręczne.
crasic
3
W praktyce w słabo załadowanym systemie plik trafi na dysk w ciągu jednej chwili. Tylko jeśli Twój edytor używa fsync()po zapisaniu pliku. Domyślne ustawienie Linuksa /proc/sys/vm/dirty_writeback_centisecsto 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ługo write()przed opróżnieniem na dysk, aby zoptymalizować przypadek, w którym zostanie wkrótce usunięty lub zmodyfikowany.
Peter Cordes,
2
+1, ponieważ sam dysk może kłamać w systemie operacyjnym . Rozumiem, że dyski wykonujące tego rodzaju buforowanie mają również wystarczającą pojemność, aby umożliwić zapisanie ich pamięci podręcznej nawet w przypadku katastrofalnej utraty mocy. To nie jest specyficzne dla systemu operacyjnego; System Windows ma mechanizm „Bezpiecznie usuń USB”, aby wykonać opróżnianie pamięci podręcznej przed odłączeniem użytkownika.
studog
1
@studog, nie byłbym tego taki pewien, szczególnie jeśli chodzi o sprzęt konsumencki. Ale to może być tylko paranoja. Ciekawie byłoby jednak przetestować.
ilkkachu
14

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 RAM
  • dowolny sieciowy system plików (NFS, CIFS / SMB, AFS, AFP,…)
  • dowolny system plików wirtualny ( sysfs, 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).

Jörg W Mittag
źródło
10
Pierwsza część tej odpowiedzi jest po prostu poświęcona dokładnemu użytemu słowu. Nie rozumiem, w jaki sposób służy to celowi innemu niż wyśmiewanie użytkownika. Oczywiście sieciowy system plików nie zapisuje na dysku lokalnym, ale pytanie wciąż tam jest.
rura
3
Jak wskazał @pipe, fakt, że istnieją systemy plików, które nie zapisują danych na dysku, ponieważ nie używają dysku do przechowywania danych, nie decyduje, czy osoby, które go mają, mogą go zapisać, czy nie. Odpowiedź wygląda jednak interesująco
JuanRocamonde
1
@pipe Jestem pewien, że użycie terminu „besserwissering” to besserwissering! Mówiąc to jako niemiecki Besserwisser z autorytetem.
Volker Siegel
11

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.

RalfFriedl
źródło
Dziękuję za odpowiedź! Czy istnieje sposób na wymuszenie zapisu na dysku określonego pliku w systemie Linux? Może link do samouczka lub strony z dokumentami, nawet pytanie SE byłoby w porządku :)
JuanRocamonde
4
Możesz wymusić zapis pliku za pomocą fsync()syscall z programu. Z poziomu powłoki wystarczy użyć syncpolecenia.
RalfFriedl
2
Istnieją (lub przynajmniej były) niektóre systemy plików w niektórych wersjach Linuksa, w których synczostał 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 CACHEjako brak działania lub natychmiast wracają z niego i wykonują go w tle.
Jörg W Mittag
9

1. Pamięć flash

Czy zależy to od typu dysku (tradycyjne dyski twarde vs. dyski półprzewodnikowe) lub jakiejkolwiek innej zmiennej, o której być może nie wiem? Czy to się dzieje (jeśli tak się dzieje) tylko w systemie Linux, czy jest to obecne w innych systemach operacyjnych?

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.

Stosując nasze ramy testowe, testujemy 17 towarowych dysków SSD od sześciu różnych dostawców, używając łącznie ponad trzech tysięcy cykli wtrysku błędów. Nasze wyniki eksperymentalne ujawniają, że 14 z 17 testowanych urządzeń SSD wykazuje zaskakujące zachowania w przypadku awarii zasilania, w tym uszkodzenie bitu, odcięte zapisy, niemożliwe do zapisania zapisy, uszkodzenie metadanych i całkowita awaria urządzenia.

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ą atomu rename(). 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 montowania noauto_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.

sourcejedi
źródło
5

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_centisecsDomyś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_centisecsto 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. (I fsyncnie 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).

Peter Cordes
źródło