Zapis o rozmiarze poniżej „PIPE_BUF” powinien być atomowy. Powinno to mieć co najmniej 512 bajtów, chociaż mogłoby być większe (wydaje się, że Linux ma to ustawione na 4096).
Zakłada się, że mówisz o wszystkich komponentach w pełni zgodnych z POSIX. Na przykład nie jest to prawdą w NFS.
Ale zakładając, że piszesz do pliku dziennika, który otworzyłeś w trybie „O_APPEND” i utrzymujesz swoje wiersze (w tym znak nowej linii) w bajtach „PIPE_BUF”, powinieneś być w stanie mieć wiele zapisów w pliku dziennika bez żadnych problemów z uszkodzeniem. Wszelkie przerwania pojawią się przed lub po zapisie, a nie w środku. Jeśli chcesz, aby integralność plików przetrwała ponowne uruchomienie, musisz również dzwonić fsync(2)
po każdym zapisie, ale to straszne dla wydajności.
Wyjaśnienie : przeczytaj komentarze i odpowiedź Oza Solomona . Nie jestem pewien, czy O_APPEND
ma to mieć PIPE_BUF
atomowość w takim rozmiarze. Jest całkowicie możliwe, że tak właśnie jest zaimplementowany w Linuksie write()
lub może to wynikać z rozmiarów bloków bazowego systemu plików.
fsync(2)
daje taką samą gwarancję, jaksync(2)
i nie ma tak dużego wpływu na wydajność.PIPE_BUF
na tej stronie dotyczy tylko potoków i FIFO, a nie zwykłych plików.Edycja: zaktualizowano w sierpniu 2017 r. Najnowszymi wynikami systemu Windows.
Jako autor proponowanego Boost.AFIO, który implementuje asynchroniczny system plików i bibliotekę plików i / o C ++, udzielę odpowiedzi wraz z linkami do kodu testowego i wyników .
Po pierwsze, O_APPEND lub równowartość FILE_APPEND_DATA środkami Windows, że przyrosty w zakresie plików maksymalny (plik „długość”) są atomowy pod współbieżnych pisarzy. Gwarantuje to POSIX, a Linux, FreeBSD, OS X i Windows wszystkie implementują to poprawnie. Samba również implementuje go poprawnie, NFS przed wersją 5 nie działa, ponieważ nie ma możliwości dołączania atomowego w formacie drutu. Więc jeśli otworzysz plik z opcją tylko do dopisywania, współbieżne zapisy nie będą się rozrywać w żadnym większym systemie operacyjnym, chyba że zaangażowany jest NFS.
Jednak równoczesne odczyty do załączników atomowych mogą powodować poszarpane zapisy w zależności od systemu operacyjnego, systemu plików i flag, z którymi otworzyłeś plik - przyrost maksymalnego zasięgu pliku jest atomowy, ale widoczność zapisów w odniesieniu do odczytów może lub nie być atomowym. Oto krótkie podsumowanie według flag, systemu operacyjnego i systemu plików:
Brak O_DIRECT / FILE_FLAG_NO_BUFFERING:
Microsoft Windows 10 z NTFS: aktualizacja atomicity = 1 bajt do 10.0.10240 włącznie, od 10.0.14393 co najmniej 1 MB, prawdopodobnie nieskończona (*).
Linux 4.2.6 z ext4: aktualizacja atomicity = 1 bajt
FreeBSD 10.2 z ZFS: aktualizacja atomicity = co najmniej 1Mb, prawdopodobnie nieskończona (*)
O_DIRECT / FILE_FLAG_NO_BUFFERING:
Microsoft Windows 10 z NTFS: zaktualizuj atomicity = do 10.0.10240 włącznie do 4096 bajtów tylko w przypadku wyrównania strony, w przeciwnym razie 512 bajtów, jeśli FILE_FLAG_WRITE_THROUGH jest wyłączone, w przeciwnym razie 64 bajty. Zauważ, że ta atomowość jest prawdopodobnie cechą PCIe DMA, a nie zaprojektowaną w. Od 10.0.14393, co najmniej 1Mb, prawdopodobnie nieskończona (*).
Linux 4.2.6 z ext4: aktualizacja atomicity = co najmniej 1Mb, prawdopodobnie nieskończona (*). Zauważ, że wcześniejsze Linuksy z ext4 zdecydowanie nie przekraczały 4096 bajtów, XFS z pewnością miał niestandardowe blokowanie, ale wygląda na to, że ostatni Linux w końcu to naprawił.
FreeBSD 10.2 z ZFS: aktualizacja atomicity = co najmniej 1Mb, prawdopodobnie nieskończona (*)
Możesz zobaczyć surowe wyniki testów empirycznych na https://github.com/ned14/afio/tree/master/programs/fs-probe . Zauważ, że testujemy pod kątem zerwanych przesunięć tylko na wielokrotnościach 512 bajtów, więc nie mogę powiedzieć, czy częściowa aktualizacja sektora 512-bajtowego byłaby zerwana podczas cyklu odczytu-modyfikacji-zapisu.
Tak więc, aby odpowiedzieć na pytanie OP, zapisy O_APPEND nie będą kolidować ze sobą, ale odczyty współbieżne z zapisami O_APPEND prawdopodobnie zobaczą rozdarte zapisy w Linuksie z ext4, chyba że O_DIRECT jest włączony, po czym zapis O_APPEND musiałby mieć rozmiar sektora wielokrotnego.
(*) „Prawdopodobnie nieskończony” wywodzi się z następujących klauzul specyfikacji POSIX:
i
ale odwrotnie:
Możesz przeczytać więcej o ich znaczeniu w tej odpowiedzi
źródło
Napisałem skrypt, aby empirycznie przetestować maksymalny atomowy rozmiar dodatku. Skrypt napisany w bashu generuje wiele procesów roboczych, z których wszystkie zapisują podpisy specyficzne dla pracownika w tym samym pliku. Następnie odczytuje plik, szukając nakładających się lub uszkodzonych podpisów. Możesz zobaczyć źródło skryptu w tym poście na blogu .
Rzeczywisty maksymalny rozmiar dołączania atomowego zależy nie tylko od systemu operacyjnego, ale także od systemu plików.
W systemie Linux + ext3 rozmiar wynosi 4096, aw systemie Windows + NTFS - 1024. Więcej rozmiarów można znaleźć w komentarzach poniżej.
źródło
echo $line >> $OUTPUT_FILE
spowoduje to pojedyncze wywołanie,write
niezależnie od rozmiaru$line
.Oto, co mówi standard: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html .
źródło