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:
Wszystkie poniższe funkcje będą atomowe względem siebie w efektach określonych w POSIX.1-2008, gdy operują na zwykłych plikach lub dowiązaniach symbolicznych ... [wiele funkcji] ... read () ... write ( ) ... Jeśli dwa wątki wywołują jedną z tych funkcji, każde wywołanie powinno 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 można udowodnić (w jakikolwiek sposób), że odczyt () danych pliku występuje po zapisie () danych, musi to odzwierciedlać metodę write (), nawet jeśli wywołania są wykonywane przez różne procesy. [Źródło]
ale odwrotnie:
Ten tom POSIX.1-2008 nie określa zachowania współbieżnych zapisów do pliku z wielu procesów. Aplikacje powinny używać jakiejś formy kontroli współbieżności. [Źródło]
Możesz przeczytać więcej o ich znaczeniu w tej odpowiedzi
fsync(2)
daje taką samą gwarancję, jaksync(2)
i nie ma tak dużego wpływu na wydajność.