Dosya UNIX'te atomik mi?


106

Genel olarak, UNIX'teki bir dosyaya birden çok işlemden eklediğimizde neyi doğal kabul edebiliriz? Veri kaybı mümkün mü (bir işlem diğerinin değişikliklerinin üzerine yazıyor)? Verilerin karışması mümkün mü? (Örneğin, her işlem bir günlük dosyasına eklenen başına bir satır ekliyor, iki satırın karışması mümkün mü?) Ek yukarıdaki anlamda atomik değilse, o zaman karşılıklı dışlamayı sağlamanın en iyi yolu nedir?

Yanıtlar:


65

"PIPE_BUF" boyutunun altındaki bir yazının atomik olduğu varsayılır. Bu, en az 512 bayt olmalıdır, ancak kolaylıkla daha büyük olabilir (linux, 4096'ya ayarlanmış gibi görünüyor).

Bu, tüm POSIX uyumlu bileşenlerden bahsettiğinizi varsayar. Örneğin, bu NFS için geçerli değildir.

Ancak, 'O_APPEND' modunda açtığınız bir günlük dosyasına yazdığınızı ve satırlarınızı (satırsonu dahil) 'PIPE_BUF' bayt uzunluğunda tuttuğunuzu varsayarsak, herhangi bir bozulma sorunu olmadan bir günlük dosyasına birden fazla yazar sahip olmanız gerekir. Herhangi bir kesinti ortada değil, yazmadan önce veya sonra gelir. Yeniden başlatmadan fsync(2)sonra dosya bütünlüğünün devam etmesini istiyorsanız , her yazma işleminden sonra da aramanız gerekir , ancak bu performans için korkunç.

Açıklama : yorumları ve Oz Süleyman'ın cevabını okuyun . Bunun atomik boyutta O_APPENDolması gerektiğinden emin değilim PIPE_BUF. Linux'un tam olarak nasıl uygulandığı tamamen mümkündür write()veya temeldeki dosya sisteminin blok boyutlarından kaynaklanıyor olabilir.


11
Aklı başında dosya sistemlerinde, fsync(2)olduğu kadar garanti verir sync(2)ve performans üzerinde o kadar büyük bir etkisi yoktur.
ephemient

4
Bundan emin misin? Bu davranış hakkında biraz bağlantı verebilir misiniz? Tanımlayıcının bir boru olup olmadığını doğruladım, ancak herhangi bir dosya için çalıştığına dair bir kanıt bulamadım . normal, NFS olmayan dosya nesneleri dahil.
Alan Franzoni

6
... / write.html'de tam olarak nerede? O_APPEND için, PIPE_BUF'den söz görmüyorum ve " dosya ofsetini değiştirme ile yazma işlemi arasında araya giren bir dosya değiştirme işlemi olmayacağına" dair söz görüyorum , ancak bunun yazma işleminin kendisinin olduğu anlamına mı geldiğinden emin değilim kesintisiz ...
akavel

6
As Bu cevap işaret, yaklaşık deyimi PIPE_BUFo sayfada sadece borular ve FIFO'lar değil, düzenli dosyalar için de geçerlidir.
Greg Inozemtsev

3
Gelen sinyallerle bu durum daha da kötüleşebilir: bugzilla.kernel.org/show_bug.cgi?id=55651 . Bu neden bir cevap olarak işaretlendi? PIPE_BUF'un dosyalarla hiçbir ilgisi yoktur.
incelendi

35

Düzenleme: Ağustos 2017'de en son Windows sonuçlarıyla güncellendi.

Eşzamansız bir dosya sistemi ve dosya i / o C ++ kitaplığı uygulayan önerilen Boost.AFIO'nun yazarı olarak test koduna ve sonuçlarına bağlantılar içeren bir cevap vereceğim .

İlk olarak, Windows'ta O_APPEND veya eşdeğer FILE_APPEND_DATA, maksimum dosya kapsamındaki artışların (dosya "uzunluğu") eşzamanlı yazarlar için atomik olduğu anlamına gelir . Bu, POSIX tarafından garanti edilir ve Linux, FreeBSD, OS X ve Windows'un tümü bunu doğru bir şekilde uygular. Samba da bunu doğru bir şekilde uygular, v5'ten önceki NFS, atomik olarak ekleme yapma yeteneğinden yoksun olduğu için bunu yapmaz. Bu nedenle, dosyanızı yalnızca ek olarak açarsanız, NFS dahil olmadıkça , herhangi bir büyük işletim sisteminde eşzamanlı yazma işlemleri birbirine göre yırtılmaz .

Ancak eşzamanlı okur atom ekler için olabilir yırtılmış yazma sistemi dosyalama, OS bağlı olarak görmek ve neler bayrakları size dosyayı açtı - maksimum dosya ölçüde olduğu atom artımı, bunlarla ilgili yazma görünürlük okur veya olmayabilir atomik ol. İşte bayraklar, işletim sistemi ve dosyalama sistemine göre hızlı bir özet:


O_DIRECT / FILE_FLAG_NO_BUFFERING yok:

NTFS ile Microsoft Windows 10: 10.0.10240'a kadar ve 10.0.10240'a kadar atomicity = 1 bayt, 10.0.14393'ten en az 1Mb, muhtemelen sonsuz (*) güncelleyin.

Ext4 ile Linux 4.2.6: güncelleme atomikliği = 1 bayt

FreeBSD 10.2, ZFS ile: güncelleme atomikliği = en az 1Mb, muhtemelen sonsuz (*)

O_DIRECT / FILE_FLAG_NO_BUFFERING:

NTFS ile Microsoft Windows 10: atomicity = 10.0.10240'a kadar ve dahil olmak üzere 4096 bayta kadar yalnızca sayfa hizalandığında, aksi takdirde FILE_FLAG_WRITE_THROUGH kapalıysa 512 bayt, diğer 64 bayt güncelleyin. Bu atomikliğin muhtemelen tasarlanmaktan çok PCIe DMA'nın bir özelliği olduğuna dikkat edin. 10.0.14393'ten beri, en az 1Mb, muhtemelen sonsuz (*).

Ext4 ile Linux 4.2.6: güncelleme atomikliği = en az 1Mb, muhtemelen sonsuz (*). Ext4'e sahip eski Linux'ların kesinlikle 4096 baytı aşmadığını, XFS'in kesinlikle özel kilitlemeye sahip olduğunu ancak son Linux'un sonunda bunu düzelttiği görülüyor.

FreeBSD 10.2, ZFS ile: güncelleme atomikliği = en az 1Mb, muhtemelen sonsuz (*)


Ham deneysel test sonuçlarını https://github.com/ned14/afio/tree/master/programs/fs-probe adresinde görebilirsiniz . Sadece 512 baytlık katlarda yırtılmış ofsetleri test ettiğimize dikkat edin, bu nedenle 512 bayt sektörün kısmi güncellemesinin okuma-değiştirme-yazma döngüsü sırasında yırtılacağını söyleyemem.

Dolayısıyla, OP'nin sorusunu yanıtlamak için, O_APPEND yazmaları birbirini etkilemeyecektir, ancak O_APPEND ile eşzamanlı okuma yazma işlemleri, muhtemelen O_DIRECT açık olmadıkça, Linux'ta ext4 ile yırtık yazmalar görecek, bunun üzerine O_APPEND yazmalarınızın sektör boyutu katları olması gerekecektir.


(*) "Muhtemelen sonsuz", POSIX spesifikasyonundaki şu maddelerden kaynaklanmaktadır:

Aşağıdaki işlevlerin tümü, normal dosyalar veya sembolik bağlantılar üzerinde çalıştıklarında POSIX.1-2008'de belirtilen efektlerde birbirine göre atomik olacaktır ... [birçok işlev] ... oku () ... yaz ( ) ... İki iş parçacığının her biri bu işlevlerden birini çağırırsa, her çağrı ya diğer çağrının belirtilen tüm etkilerini görecek ya da hiçbirini görmeyecektir. [Kaynak]

ve

Yazılar, diğer okuma ve yazmalara göre serileştirilebilir. Bir dosya verisinin () okunmasının () bir verinin yazılmasından () sonra gerçekleştiği kanıtlanabiliyorsa, çağrılar farklı işlemlerle yapılsa bile bu write () öğesini yansıtmalıdır. [Kaynak]

ama tersine:

Bu POSIX.1-2008 cilt, bir dosyaya birden çok işlemden eşzamanlı yazma davranışını belirtmez. Uygulamalar bir tür eşzamanlılık denetimi kullanmalıdır. [Kaynak]

Bunların anlamı hakkında daha fazla bilgiyi bu cevapta okuyabilirsiniz.


29

Maksimum atomik eklenti boyutunu deneysel olarak test etmek için bir komut dosyası yazdım. Bash ile yazılan komut dosyası, hepsi aynı dosyaya işçiye özgü imzalar yazan birden çok çalışan işlemi üretir. Ardından, çakışan veya bozuk imzaları arayarak dosyayı okur. Komut dosyasının kaynağını bu blog gönderisinde görebilirsiniz .

Gerçek maksimum atomik uzantı boyutu yalnızca işletim sistemine göre değil, dosya sistemine göre de değişir.

Linux + ext3'te boyut 4096'dır ve Windows + NTFS'de boyut 1024'tür. Daha fazla boyut için aşağıdaki yorumlara bakın.


Linux'ta hangi dosya sistemini test ettiniz? Dosya sistemi blok boyutlarına dayanıp dayanmadığını merak ediyorum.
freiheit

@freiheit ext3'te test ettiğimde inanıyorum. Başka bir FS'de çalıştırırsanız ve farklı bir sonuç alırsanız, lütfen bir yorum gönderin.
Oz Solomon

3
@OzSolomon, betiğinizi Debian 7.8'de kullandım ve hem ext4 bölümümde hem de bir tmpfs bağlayıcımda yalnızca 1008 bayta (1024 - 16 bayt ek yük?) Kadar ve dahil olmak üzere atomik yazımlar alabildim. Bunun ötesinde her şey her seferinde yolsuzlukla sonuçlandı.
Eric Pruitt

6
Testiniz , boyutuna bakılmaksızın echo $line >> $OUTPUT_FILEiçin tek bir çağrı ile sonuçlanacağını varsayıyor . write$line
Tomas

16

Standardın söylediği şu: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html .

Eğer O_APPENDdosya durumu bayrakların bayrak ayarlanırsa, ofset dosyası, her yazma öncesinde dosyanın sonuna belirlenir ve hiçbir müdahalede dosya değiştirme işlemi ofset dosya ve yazma işlemini değiştirerek arasında meydana edecektir.


20
"ara" - peki ya yazma sırasındaki müdahaleler , benim anlayışıma göre hangisi "ara" dan sonra oluyor? (Yani: <change_offset_action> ... "the_between_period" ... <write_action>) - bunun garantisinin olmadığını anlamalı mıyım?
akavel

@akavel kabul etti; yazının kendisinin atomik olduğuna dair hiçbir garanti yoktur. Ancak kafam karıştı: Alıntıda verilen garantiye dayanarak, aynı dosyayı ekleyen çok iş parçacıklı bir uygulamanın farklı yazılı kayıtların bölümlerini karıştırmayacağı sonucuna varabiliriz. Ancak OzSolomon tarafından bildirilen deneylerden bu varsayımın bile ihlal edildiğini görüyoruz. Neden?
en fazla

@max üzgünüm, sorunuzu alamadım korkuyorum: birincisi, OzSolomon deneyi çok olan süreç değil, bir çok dişli (tek işlem) uygulaması; ikinci olarak, "çok iş parçacıklı bir uygulamanın [...] karışmayacağı" sonucunu nasıl çıkardığınızı anlamıyorum - bu, yorumumda bahsettiğim gibi, Bastien'den alıntının garanti ettiğini tam olarak görmediğim şey. Sorunuzu netleştirebilir misiniz?
akavel

2
Hmm, bu yorumu yazdığım zaman kendi mantığımı yeniden oluşturamıyorum ... Evet, yorumunuz doğruysa, o zaman elbette farklı kayıtlar karışabilir. Ama şimdi Bastien'in sözünü tekrar okuduğuma göre, sanırım bu hiç kimsenin "yazma sırasında" sözünü kesemeyeceği anlamına gelmeli - aksi takdirde standarttaki paragrafın tamamı işe yaramaz, kelimenin tam anlamıyla hiçbir garanti vermez (yazmanın gerçekleşeceği bile sonunda, "yazma" adımı yürütülürken başka biri ofseti hareket ettirebileceğinden.
en fazla
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.