Sayfa önbelleğine% 100 sayfalanmış bir dosya başka bir işlemle değiştirildiğinde ne olur?


14

Bir sayfa önbellek sayfası değiştirildiğinde, kirli olarak işaretlendiğini ve bir geri yazma gerektirdiğini biliyorum, ancak ne zaman olur:

Senaryo: Yürütülebilir bir dosya olan / apps / EXE dosyası, sayfa önbelleğine tamamen sayfalanmış (tüm sayfaları önbellek / bellekte) ve P işlemi tarafından yürütülüyor

Sürekli sürüm daha sonra / apps / EXE dosyasını yepyeni bir yürütülebilir dosyayla değiştirir.

Varsayım 1: P sürecinin (ve eski yürütülebilir dosyayı referans alan bir dosya tanımlayıcısına sahip olan herkesin) eski, bellekte / apps / EXE'de sorun olmadan kullanmaya devam edeceğini ve bu yolu yürütmeye çalışan yeni işlemlerin yeni yürütülebilir dosya.

Varsayım 2: Dosyanın tüm sayfaları belleğe eşlenmezse, dosyadan değiştirilen sayfalar gerektiren bir sayfa hatası olana ve muhtemelen bir segfault oluşana kadar işlerin iyi olacağını varsayıyorum.

Soru 1: Dosyanın tüm sayfalarını vmtouch gibi bir şeyle kilitlerseniz, bu senaryo hiç değişiyor mu?

Soru 2: / apps / EXE uzak bir NFS üzerindeyse, bu bir fark yaratır mı? (Sanmıyorum)

Lütfen 2 varsayımımı düzeltin veya doğrulayın ve 2 sorumu yanıtlayın.

Bunun bir çeşit 3.10.0-957.el7 çekirdeği olan bir CentOS 7.6 kutusu olduğunu varsayalım.

Güncelleme: Daha fazla düşünerek, bu senaryonun diğer kirli sayfa senaryolarından farklı olup olmadığını merak ediyorum.

Sanırım yeni ikili yazma işlemi tüm sayfalanmış beri tüm önbellek sayfaları bir okuma yapacak ve alacak ve daha sonra tüm bu sayfalar kirli işaretlenir. Eğer tıkanmışlarsa, ref sayısı sıfıra düştükten sonra çekirdek belleği işgal eden işe yaramaz sayfalar olacaktır.

Şu anda yürütülen programlar sona erdiğinde, başka herhangi bir şey yeni ikiliyi kullanacağından şüpheleniyorum. Her şeyin doğru olduğunu varsayarsak, sadece dosyanın sadece bir kısmı disk belleği içine alındığında ilginç olur.


Sadece açık hale getirmek için, bir dosyayı değiştirmek büyük bir şey olmayacaktır (uygulama tarafından yeniden açılıp açılmadığına ve uygulamanın değiştirilmiş içeriğe nasıl tepki verdiğine bağlı olarak), ancak mmaped dosyalarını değiştirmek çökme uygulamalarını ciddiye alabilir (bu yaygın bir sorundur) mmaped dizin girişi olan bir zip dosyası değiştirildiğinde java dünyasında). Ancak platforma bağlıdır, mmaped bölgelerin değişikliği görüp görmediği garanti edilmez.
Eckes

Yanıtlar:


12

Sürekli sürüm daha sonra / apps / EXE dosyasını yepyeni bir yürütülebilir dosyayla değiştirir.

Bu önemli kısım.

Yeni bir dosyanın serbest bırakılma şekli, yeni bir dosya (ör. /apps/EXE.tmp.20190907080000) Oluşturmak , içeriği yazmak, izinleri ve sahipliği ayarlamak ve son olarak (2) yeniden adlandırarak (2) /apps/EXEeski dosyayı değiştirmektir.

Sonuç, yeni dosyanın yeni bir inode numarasına sahip olmasıdır (yani aslında farklı bir dosyadır.)

Ve eski dosyanın kendi inode numarası vardı, bu dosya adı artık ona işaret etmese bile hala etrafta duruyor (veya artık bu inode'a işaret eden dosya adları yok.)

Yani, burada anahtar Linux'ta "dosyalar" hakkında konuştuğumuzda, bir dosya açıldığında, inode dosyaya sakladığımız referans olduğundan, çoğunlukla "inodlar" hakkında konuşuyoruz.

Varsayım 1 : P sürecinin (ve eski yürütülebilir dosyayı referans alan bir dosya tanımlayıcısına sahip olan herkesin) eski, bellekte / apps / EXE'de sorun olmadan kullanmaya devam edeceğini ve bu yolu yürütmeye çalışan yeni işlemlerin yeni yürütülebilir dosya.

Doğru.

Varsayım 2 : Dosyanın tüm sayfaları belleğe eşlenmezse, dosyadan değiştirilen sayfalar gerektiren bir sayfa hatası olana ve muhtemelen bir segfault oluşana kadar işlerin iyi olacağını varsayıyorum.

Yanlış. Eski inode hala ortadadır, bu nedenle eski ikili dosyayı kullanan işlemdeki sayfa hataları yine de bu sayfaları diskte bulabilir.

Bunun eski etkilerini çalıştıran işlemin /proc/${pid}/exesembolik bağlantısına (ya da eşdeğer olarak lsofçıktıya) bakarak /app/EXE (deleted), adın artık orada olmadığını, ancak inodeun hala orada olduğunu belirten bazı etkilerini görebilirsiniz .

İkili tarafından kullanılan disk alanının yalnızca işlem sona erdikten sonra serbest bırakılacağını da görebilirsiniz (bu inode açıkken tek işlem olduğunu varsayarsak.) dfSüreci öldürmeden önce ve sonra çıktısını kontrol edin , boyutuna göre düştüğünü göreceksiniz Artık bu olmadığını düşündüğün o eski ikili dosyadan.

BTW, bu sadece ikili dosyalar için değil, açık dosyalar için de geçerlidir. Bir işlemdeki bir dosyayı açar ve dosyayı kaldırırsanız, bu işlem dosyayı kapatana kadar (veya ölene kadar) diskte tutulur. Sabit bağlantıların diskteki bir kaç düğüme işaret ettiği adın sayacını tutmasına benzer şekilde, dosya sistemi sürücüsü (Linux çekirdeğinde) bellekteki bu inode'a kaç referansın var olduğunu karşılar ve inode'u yalnızca çalışan sistemden tüm referanslar serbest bırakıldıktan sonra serbest bırakır.

Soru 1 : Dosyanın tüm sayfalarını vmtouch gibi bir şeyle kilitlerseniz senaryo değişir

Bu soru, sayfaları kilitlememenin segfaultlara neden olacağı yanlış varsayımına 2 dayanmaktadır. Olmaz.

Soru 2 : / apps / EXE uzak bir NFS üzerindeyse, bu bir fark yaratır mı? (Sanmıyorum)

O var demek öyle çoğu zaman aynı şekilde çalışır ve, ancak bazı "Sorunlar" NFS ile vardır.

Bazen NFS'de hala açık olan bir dosyayı silmenin eserlerini görebilirsiniz (bu dizinde gizli bir dosya olarak görünür).

Ayrıca, NFS sunucusu yeniden başlatıldığında bunların "yeniden karıştırılmayacağından" emin olmak için NFS dışa aktarmalarına cihaz numaraları atamanın bir yolu vardır.

Ancak ana fikir aynı. NFS istemci sürücüsü hala inode kullanıyor ve inode hala başvurulurken dosyaları (sunucuda) tutmaya çalışacak.


1
Rename (2), eski ad dosyasının ref sayısı sıfıra gelene kadar engelliyor mu?
Gregg Leventhal

2
Hayır, yeniden adlandır (2) engellenmez. Eski inode potansiyel olarak çok uzun süre korunur.
filbranden

1
@ Mosvy'nin neden yürütülmekte olan bir dosyaya yazamadığınıza (ETXTBSY alıyorsunuz) cevabına bakınız. Bağlantıyı kaldırma ve yeni oluşturma, yeniden adlandırma efektiyle aynı etkiye sahiptir: yeni bir inode ile sonuçlanırsınız. (Yeniden adlandırma daha iyidir çünkü dosya adının mevcut olmadığı bir an yoktur, bu yeni
inode'yu gösterecek

4
@GreggLeventhal: "Kullandığım sürekli yayın süreci hakkında geçici dosyalar kullandığından emin olmanızı sağlayan ne varsayımınız var?" - Çünkü Unix var olduğu sürece, bunu yapmanın tek aklı yolu budur ve olmuştur. renameatomik olduğu garanti edilen tek dosya ve dosya sistemi işlemidir (dosya sistemini veya cihaz sınırlarını geçmediğimizi varsayarsak), bu nedenle "geçici dosya oluştur ve sonra rename" dosyaları güncellemek için standart kalıptır. Örneğin, Unix'teki her metin düzenleyicinin kullandığı şey de budur.
Jörg W Mittag

1
@ grahamj42: POSIX'in renamebir parçasıdır. Verilen, ISO C'ye (mevcut taslakta bölüm 7.21.4.2) referans olarak dahil edilmiştir, ancak oradadır.
Jörg W Mittag

7

Varsayım 2: Dosyanın tüm sayfaları belleğe eşlenmezse, dosyadan değiştirilen sayfalar gerektiren bir sayfa hatası olana ve muhtemelen bir segfault oluşana kadar işlerin iyi olacağını varsayıyorum.

Hayır, bu olmayacak, çünkü çekirdek şu anda yürütülen bir dosyanın içindeki herhangi bir şeyin yerini almak için açmanıza izin vermeyecektir. Böyle bir eylem ETXTBSY[1] ile başarısız olacaktır :

cp /bin/sleep sleep; ./sleep 3600 & echo none > ./sleep
[9] 5332
bash: ./sleep: Text file busy

Dpkg, etc bir ikili dosyayı güncellediğinde, üzerine yazmaz, ancak rename(2)dizin girişini tamamen farklı bir dosyaya yönlendiren kullanır ve hala eski dosyaya eşleme veya açık tutamaçları olan işlemler sorunsuz olarak kullanmaya devam eder .

[1] bu tür bir koruma "metin" (canlı kod / yürütülebilir) olarak da düşünülebilecek diğer dosyalara genişletilmez: paylaşılan kütüphaneler, java sınıfları, vb. başka bir işlem tarafından eşleştirilmiş ise böyle bir dosyayı değiştirerek olacaktır kilitlenmesine neden. Linux'ta dinamik bağlayıcı MAP_DENYWRITEbayrağı bayrağa geçer mmap(2), ancak hata yapmaz - herhangi bir etkisi yoktur.


1
Dpkg senaryosunda, yeniden adlandırma tamamlandığında / apps / EXE için dentry yeni ikilinin inode'una başvuracak şekilde yeniden adlandırma tamamlanır mı? Eskisine daha fazla referans olmadığında? Bu nasıl çalışıyor?
Gregg Leventhal

2
rename(2)R4 atomiktir; tamamlanır tamamlanmaz dir girdisi yeni dosyaya başvurur. Bu noktada hala eski dosyayı kullanan işlemler, yalnızca mevcut eşlemeler yoluyla veya dosyaya açık tutamaçlarla erişebilir (artık artık erişilemeyen artık bir yetim dişçiliğine başvurabilir /proc/PID/fd).
mosvy

1
Cevabınızı en çok beğeniyorum çünkü ETXTBSY bahsiniz beni tüm sorularıma cevap veren bu utcc.utoronto.ca/~cks/space/blog/unix/WhyTextFileBusyError'a yönlendirdi.
Gregg Leventhal

4

filbranden'in cevabı, sürekli yayınlama işleminin dosyaların doğru atomik olarak değiştirilmesini sağladığını varsayarsa doğrudur rename. Dosya yerinde değil, değiştirirse, işler farklıdır. Ancak zihinsel modeliniz hala yanlış.

Sayfa önbelleği standart sürüm ve değiştirilen sürüm olduğundan , diskte değişiklik yapma ve sayfa önbelleğiyle tutarsız olma olasılığı yoktur . Bir dosyaya yapılan tüm yazma işlemleri sayfa önbelleği üzerinden yapılır. Orada zaten varsa, mevcut sayfalar değiştirilir. Henüz mevcut değilse, kısmi bir sayfayı değiştirme girişimleri tüm sayfanın önbelleğe alınmasına ve ardından zaten önbelleğe alınmış gibi değişikliklere neden olur. Bir sayfanın tamamını veya daha fazlasını kapsayan yazma işlemleri, okuma adımını sayfalara ayırarak optimize edebilir (ve neredeyse kesin olarak yapar). Her durumda, dosyanın önbelleğinde var olan bir dosyanın (*) yalnızca tek bir standart değiştirilebilen sürümü vardır. .

(*) Hafifçe yalan söyledim. NFS ve diğer uzak dosya sistemleri için birden fazla olabilir ve bunlar tipik olarak (hangisinin ve hangi mount ve sunucu tarafı seçeneklerinin kullanıldığına bağlı olarak) atomisite ve yazma semantiği için doğru bir şekilde uygulamaz. Bu yüzden birçoğumuz onları temelde kırık olarak görüyor ve kullanımla eşzamanlı yazmaların olacağı durumlar için kullanmayı reddediyoruz.

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.