Python's file.flush () tam olarak ne yapıyor?


137

Bunu Dosya Nesneleri için Python belgelerinde buldum :

flush () mutlaka dosyanın verilerini diske yazmaz. Bu davranışı sağlamak için önce flush () ve ardından os.fsync () kullanın.

Benim sorum şu: Python tam olarak ne flushyapıyor? Diske veri yazmaya zorladığını düşündüm, ama şimdi olmadığını görüyorum. Neden?

Yanıtlar:


220

Genellikle iki tamponlama seviyesi vardır:

  1. Dahili arabellekler
  2. İşletim sistemi arabellekleri

Dahili arabellekler, programladığınız çalışma zamanı / kütüphane / dil tarafından oluşturulan arabelleklerdir ve her yazma için sistem çağrılarından kaçınarak işleri hızlandırmayı amaçlamaktadır. Bunun yerine, bir dosya nesnesine yazdığınızda, arabelleğine yazarsınız ve arabellek her dolduğunda veriler sistem çağrıları kullanılarak gerçek dosyaya yazılır.

Ancak, işletim sistemi arabellekleri nedeniyle bu, verilerin diske yazıldığı anlamına gelmeyebilir . Bu sadece verilerin çalışma süreniz tarafından tutulan arabelleklerden işletim sistemi tarafından tutulan arabelleklere kopyalandığı anlamına gelebilir.

Bir şey yazarsanız ve arabellekte sona ererse (yalnızca) ve makinenize güç kesilirse, makine kapatıldığında bu veriler diskte değildir.

Böylece, size yardımcı olmak için ilgili nesneler üzerinde flushve fsyncyöntemlerine sahipsiniz .

Birincisi, flushbir program arabelleğinde kalan verileri gerçek dosyaya yazacaktır. Genellikle bu, verilerin program arabelleğinden işletim sistemi arabelleğine kopyalanacağı anlamına gelir.

Özellikle bunun anlamı, başka bir işlem aynı dosyayı okumak için açıksa, dosyaya yeni temizlediğiniz verilere erişebilmesidir. Ancak, diskte "kalıcı olarak" depolandığı anlamına gelmez.

Bunu yapmak için, os.fsynctüm işletim sistemi arabelleklerinin bulundukları depolama aygıtlarıyla senkronize edilmesini sağlayan yöntemi çağırmanız gerekir , başka bir deyişle, bu yöntem işletim sistemi arabelleklerinden diske veri kopyalar.

Genellikle her iki yöntemle de uğraşmanıza gerek yoktur, ancak diskte gerçekten neyin bittiği hakkında paranoyaların iyi olduğu bir senaryodaysanız, her iki çağrıyı da belirtildiği gibi yapmanız gerekir.


2018'de Zeyilname.

Önbellek mekanizmalarına sahip disklerin artık 2013'te olduğundan çok daha yaygın olduğuna dikkat edin, bu yüzden artık daha fazla önbellek ve arabellek seviyesi var. Ben varsayalım bu tamponlar ve senkronizasyon / floş çağrılarıyla ele alınacaktır, ama gerçekten bilmiyorum.


10
Yapıyı kullandığımda with file('blah') as fd: #dostuff, dosya tanımlayıcısının kapatılmasını garanti ettiğini biliyorum. Aynı zamanda temizler veya senkronize eder mi?
Marcin

3
@ Marcin: Yıkar, ancak senkronize DEĞİLDİR.
Alex Ben

8
fsyncatomisite için gereklidir. bir dosyayı kapatmayı, yeniden açmayı ve içeriğinizi fsyncortada olmadan bulmayı bekleyemezsiniz . Genellikle çalışır, ancak örneğin ext4 ve varsayılan bağlama seçenekleriyle linux üzerinde çalışmaz. Ayrıca fsync, 1: fsync devre dışı bırakılabilir (dizüstü bilgisayar modu ile) ve 2: sabit disk dahili arabelleğe alması talimatı verilemeyeceğinden, tablalardaki ütüyü gerçekten mıknatısla çevirmesi garanti edilmez.
v.oddou

1
dosya başka bir işlem tarafından yazılmışsa, bir işletim sisteminin arabelleğini tüm dosyalar için temizlemenin bir yolu var mı?
Nacht

1
fsync nispeten pahalıdır. Genel olarak, disk erişimi için% 100 ACID uyumluluğuna ve dayanıklılığa ihtiyaç duyan kritik görev yazılımı yazmıyorsunuzdur ve muhtemelen ağrının farkındasınızdır ve bu garantileri almak için atabileceğiniz adımların farkında olmalısınız . Fsync çağrıldığında, verileri diske yazmak için fiziksel disk erişiminin gerçekleşmesi beklenirken, yıkama ve kapatma yalnızca verilerin önbelleğe taşınmasını bekler. Hız farkı muhtemelen birkaç büyüklük sırasıdır.
Lasse V. Karlsen

10

Çünkü işletim sistemi bunu yapmayabilir. Yıkama işlemi, dosya verilerini RAM'deki dosya önbelleğine zorlar ve oradan işletim sisteminin gerçekte diske göndermesi iştir.


6
Haklısınız, ancak actuallyburada göreceli: hedef cihazda yazma önbelleği etkinleştirilmişse, veriler os.fsync()geri döndüğünde gerçek plaklara / yongalara ulaşmamış olabilir .
Frédéric Hamidi

7

İşletim sisteminin arabelleği dosyaya yazmasına neden olması gereken dahili arabelleği temizler. [1] Python, aksi yönde yapılandırmadıkça işletim sisteminin varsayılan arabelleğini kullanır.

Ancak bazen işletim sistemi hala işbirliği yapmamayı tercih ediyor. Özellikle Windows / NTFS'deki yazma gecikmeleri gibi harika şeylerle. Temel olarak dahili tampon temizlenir, ancak OS arabelleği hala üzerinde tutulur. Bu nedenle işletim sistemine os.fsync()bu durumlarda diske yazmasını söylemelisiniz .

[1] http://docs.python.org/library/stdtypes.html


0

Temel olarak, flush () RAM arabelleğinizi temizler, gerçek gücü daha sonra yazmaya devam etmenize izin vermesidir - ancak dosyaya en iyi / en güvenli yazma özelliği olarak düşünülmemelidir. Daha fazla veri gelmesi için RAM'inizi yıkıyor, hepsi bu. Verilerin güvenli bir şekilde dosyaya yazıldığından emin olmak istiyorsanız bunun yerine close () öğesini kullanın.

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.