Czy file append atomic jest w Unixie?

Ogólnie rzecz biorąc, co możemy wziąć za pewnik, gdy dodajemy do pliku w Uniksie z wielu procesów? Czy możliwa jest utrata danych(jeden proces nadpisuje zmiany drugiego)? Czy dane mogą zostać zniekształcone? (Na przykład, każdy proces dołącza jedną linię do pliku dziennika, czy to możliwe, że dwie linie zostaną zniekształcone?) Jeśli dodatek nie jest atomowy w powyższym sensie, to jaki jest najlepszy sposób zapewnienia wzajemnego wykluczenia?

Author: Peter Cordes, 2009-07-20

4 answers

Zapis poniżej rozmiaru 'PIPE_BUF' ma być atomowy. Powinno to wynosić co najmniej 512 bajtów, choć łatwo może być większe (linux wydaje się mieć ustawiony na 4096).

Zakładamy, że mówimy o wszystkich komponentach w pełni zgodnych z POSIX. Na przykład, nie jest to prawdą w NFS.

Ale zakładając, że zapisujesz do pliku dziennika, który otworzyłeś w trybie 'O_APPEND' i utrzymujesz linie (w tym nową linię) w bajtach 'PIPE_BUF', powinieneś mieć wiele zapisów do plik dziennika bez problemów z uszkodzeniem. Wszelkie przerwania pojawią się przed lub po zapisie, a nie w środku. Jeśli chcesz, aby integralność pliku przetrwała restart, musisz również wywołać fsync(2) po każdym zapisie, ale to jest straszne dla wydajności.

Wyjaśnienie: przeczytaj komentarze i odpowiedź Oz Salomona. Nie jestem pewien, czy O_APPEND powinna mieć taką atomiczność PIPE_BUF. Jest całkowicie możliwe, że tak właśnie zaimplementowano Linuksa write(), lub może być to spowodowane do rozmiaru bloków bazowego systemu plików.

 52
Author: freiheit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:27

Edit: Zaktualizowano Sierpień 2017 z najnowszymi wynikami systemu Windows.

Dam ci odpowiedź z linkami do kodu testowego i wyników jako autor zaproponowanego Boost.Afio , który implementuje Asynchroniczny system plików i bibliotekę we/wy C++.

Po pierwsze, O_APPEND lub równoważny FILE_APPEND_DATA w systemie Windows oznacza, że przyrost maksymalnego rozmiaru pliku (Plik "długość") jest atomic pod współbieżnymi zapisami. Jest to gwarantowane przez POSIX i Linux, FreeBSD, OS X i Windows Wszystkie implementują go poprawnie. Samba również implementuje go poprawnie, NFS przed v5 nie, ponieważ nie ma możliwości formatu drutu do dołączania atomicznie. Więc jeśli otworzysz plik z append-only, współbieżne zapisy nie będą się rozszczepiać względem siebie na żadnym głównym systemie operacyjnym , chyba że chodzi o NFS.

Jednak jednoczesne odczytuje do Atomic appends Może zobaczyć torn zapisuje w zależności od systemu operacyjnego, systemu plików i jakie flagi otworzyłeś plik - przyrost maksymalnego rozmiaru pliku jest atomowy, ale widoczność zapisów w odniesieniu do odczytów może być atomowa lub nie. Oto krótkie podsumowanie przez flagi, system operacyjny i system plików:


No O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 z NTFS: update atomicity = 1 bajt do 10.0.10240 włącznie, od 10.0.14393 co najmniej 1MB, prawdopodobnie nieskończony (*).

Linux 4.2.6 z ext4: update atomicity = 1 bajt

FreeBSD 10.2 z ZFS: update atomicity = co najmniej 1MB, prawdopodobnie nieskończony (*)

O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 z NTFS: update atomicity = do 10.0.10240 włącznie do 4096 bajtów tylko jeśli strona wyrównana, w przeciwnym razie 512 bajtów jeśli file_flag_write_through off, w przeciwnym razie 64 bajty. Zauważ, że ta atomiczność jest prawdopodobnie cechą PCIe DMA, a nie zaprojektowaną w. Od 10.0.14393, co najmniej 1Mb, prawdopodobnie nieskończony (*).

Linux 4.2.6 z ext4: update atomicity = at minimum 1Mb, prawdopodobnie nieskończone (*). Zauważ, że wcześniejsze Linuksy z ext4 zdecydowanie nie przekraczały 4096 bajtów, XFS z pewnością miał własne blokowanie, ale wygląda na to, że najnowszy Linux w końcu to naprawił.

FreeBSD 10.2 z ZFS: update atomicity = co najmniej 1MB, prawdopodobnie nieskończony ( * )


Możesz zobaczyć surowe wyniki badań empirycznych na https://github.com/ned14/afio/tree/master/programs/fs-probe . Uwaga testujemy dla zerwanych offsetów tylko na wielokrotnościach 512 bajtów, więc I nie można powiedzieć, czy częściowa aktualizacja 512-bajtowego sektora ulegnie rozerwaniu podczas cyklu odczytu-modyfikacji-zapisu.

Tak więc, aby odpowiedzieć na pytanie OP, zapis O_APPEND nie będzie kolidował ze sobą, ale odczyt współbieżny do zapisu O_APPEND prawdopodobnie będzie widział rozdarte zapisy w Linuksie z ext4, chyba że o_direct jest włączony, po czym Twój zapis o_append musi być wielosektorowy.


(*) "prawdopodobnie nieskończony" wynika z tych klauzul w specyfikacji POSIX:

Wszystkie następujące funkcje są atomowe w odniesieniu do każdego inne w efektach określonych w POSIX.1-2008 kiedy działają na zwykłe pliki lub dowiązania symboliczne ... [wiele funkcji]... read ()... write ()... Jeśli dwa wątki wywołują jedną z tych funkcji, każde wywołanie musi albo zobaczyć wszystkie określone efekty drugiego wywołania, albo żaden z nich. [Źródło]

I

Zapisy mogą być serializowane w odniesieniu do innych odczytów i zapisów. Jeśli a Czytaj() danych pliku może być udowodnione (w dowolny sposób), aby wystąpić po write () danych, musi odzwierciedlać to write (), nawet jeśli wywołania są wytwarzane przez różne procesy. [Źródło]

Ale odwrotnie:

Ten wolumin POSIX.1-2008 nie określa zachowania współbieżnych zapisuje do pliku z wielu procesów. Aplikacje powinny korzystać z niektórych forma kontroli współbieżności. [Źródło]

Możesz przeczytać więcej o znaczeniu te w tej odpowiedzi

 27
Author: Niall Douglas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-21 18:19:45

Napisałem skrypt, aby empirycznie przetestować maksymalną liczbę atomów. Skrypt, napisany w bash, wywołuje wiele procesów roboczych, z których wszystkie zapisują sygnatury specyficzne dla danego workera do tego samego pliku. Następnie odczytuje plik, szukając nakładających się lub uszkodzonych sygnatur. Możesz zobaczyć źródło skryptu w tym blogu post .

Rzeczywisty maksymalny rozmiar atomowych załączników różni się nie tylko w zależności od systemu operacyjnego, ale także systemu plików.

Na Linuksie + ext3 rozmiar to 4096, a na Windows+NTFS rozmiar to 1024. Więcej rozmiarów znajdziesz w komentarzach poniżej.

 18
Author: Oz Solomon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 20:25:54

Oto, co mówi standard: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html .

Jeśli ustawiona jest znacznik O_APPEND znaczników statusu pliku, przesunięcie pliku jest ustawiane na koniec pliku przed każdym zapisem i nie może wystąpić Żadna interweniująca operacja modyfikacji pliku pomiędzy zmianą przesunięcia pliku a operacją zapisu.

 14
Author: Bastien Léonard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-20 17:06:05