Ders 17 / 22
Dosya Sistemleri
Aynı dosyaları taşıyan dizin üç iç düzende 449.985.000, 125.312 ve 59.800 karşılaştırmaya mal oluyor; sağlama taşımayan tasarımda bozuk bloğa dokunan 54 okumanın 54'ü hatasız dönüyor.
İçindekiler
Önceki ders bölümü aygıtın gövdesine çizilmiş bir aralık olarak bıraktı: başlangıcı, bitişi ve bir tür etiketi olan, içi hakkında hiçbir şey söylenmeyen bir parça. O aralığın içine bir düzen kurulduğu anda birkaç karar alınır ve bu kararların çoğu sonradan değiştirilemez.
Bu dersin sorusu şudur: aynı bölümde, aynı dosyalarla, farklı tasarımlar hangi noktalarda ayrışır. Ölçülecek iki eksen var — bir dizinde ad aramanın maliyeti ve bozulmuş bir bloğun okuma sırasında fark edilip edilmediği. İkisi de sayılabilir ve ikisi de araç çıktısında görünmez.
Bir Dosya Sistemi Ne Tutar
Bir dosya sistemi (file system) dört ayrı defteri aynı bölümün içinde tutar. Birincisi ad defteridir: dizin girdileri, adı bir kimliğe bağlar. İkincisi meta veri defteridir: her dosyanın boyutu, izinleri, sahibi, zaman damgaları ve içeriğinin hangi bloklarda durduğu. Üçüncüsü alan defteridir: hangi blokların dolu, hangilerinin boş olduğu. Dördüncüsü tutarlılık defteridir: bir güncelleme yarıda kalırsa diskteki yapıların birbiriyle uyumlu kalmasını sağlayan kayıt.
Bu dört defterin nasıl tutulacağı tasarımdan tasarıma değişir ve fark buradan doğar. Karşılaşılan aileler arasında XFS, Btrfs, ZFS ve genişletilmiş dosya sistemi ailesi sayılabilir; bu ders adları değil, aralarındaki eksenleri ölçer. Eksenler dörttür: meta veri defterinin boyutu biçimlendirme anında mı sabitlenir yoksa gerektikçe mi büyür; ad defteri sıralı bir liste midir yoksa aranabilir bir yapı mıdır; alan defteri blok blok mu yoksa bitişik aralıklar hâlinde mi tutulur; okunan bloğun bozulmadığı sınanır mı.
Hangi ailenin öntanımlı olarak kurulacağı dağıtıma göre değişir ve bu ders bir aileyi diğerine üstün saymaz. Ölçülen şey seçimin bedelidir, sıralaması değil. Bir eksende ucuz olan tasarım başka bir eksende pahalıdır ve hangi eksenin ağır bastığı iş yükünün kendisine bağlıdır; iş yükü değiştiğinde karar da eskir, ama dosya sistemi yerinde durmaya devam eder.
Kurulmuş bir bölümün hangi tasarımı taşıdığı okunarak öğrenilir. lsblk -f her bölümün tür
etiketini ve kimliğini yazar, blkid aynı bilgiyi tek tek verir. Aşağıdaki döküm biçimi
gösteren bir örnek dökümdür; çalıştırılmamıştır ve bu derste hiçbir sayı iddiası buradan
gelmez.
NAME FSTYPE FSVER LABEL UUID MOUNTPOINT sdb ├─sdb1 ext4 1.0 kok 11111111-1111-1111-1111-1 / ├─sdb2 xfs veri 22222222-2222-2222-2222-2 /veri ├─sdb3 ext4 1.0 gunluk 33333333-3333-3333-3333-3 /gunluk └─sdb4 swap 1 takas 44444444-4444-4444-4444-4 [SWAP]
Dökümdeki kimlik alanı sonraki derslerde işe yarayacak: bir bölümün adı değişebilir, kimliği değişmez.
Biçimlendirme Anında Sabitlenen Sayılar
Bir bölüme dosya sistemi kurmak, o bölümün başına bir üstbilgi yazıp defterlerin yerini ayırmaktır. Bu işlem bir dizi sayıyı sabitler ve sabitlenenlerin çoğu sonradan değiştirilemez ya da ancak dosya sistemi boşaltılarak değiştirilebilir.
Sabitlenen ilk sayı blok boyudur: dosya sisteminin ayırdığı en küçük birim. İkincisi meta veri kaydı sayısıdır; sabit tablo tutan tasarımlarda bu sayı biçimlendirme anında belirlenir ve dosya sistemi büyütülmedikçe artmaz. Üçüncüsü dizinin iç düzenidir ve aşağıda ölçülüyor. Dördüncüsü sağlamanın hangi defterleri kapsadığıdır. Beşincisi tutarlılık kaydının kipidir: yalnız meta veri mi günlüğe alınacak yoksa veri de mi. İşletim Sistemi Kavramları kursundaki dosya sistemi soyutlaması dersi günlüklü düzenin yazma çarpanını ölçmüştü; o ölçüm burada tekrarlanmaz.
Bir de alan defterinin biçimi vardır. Blok listesi tutan bir tasarımda her blok için bir kayıt gerekir; bitişik aralık tutan bir tasarımda peş peşe uzanan yüz blok tek kayıttır. İkincisi büyük ve parçalanmamış dosyalarda çok daha az meta veri üretir, parçalanma arttıkça kazancı erir. Hangi biçimin seçileceği dosya boyu dağılımına bağlıdır ve bu dağılım biçimlendirme anında bilinmez; karar tahminle verilir.
Yıkıcı komut sınırı burada başlıyor: bir bölümü biçimlendiren komut, o bölümdeki her şeyi geri alınamaz biçimde siler ve yanlış bölüm adı yazılırsa uyarı vermeden çalışabilir. Bu ders biçimlendirme komutunu çalıştırılabilir tam biçimde vermez. Güvenli sınama yolu, bir dosyayı geri döngü aygıtı olarak bağlayıp denemeyi orada yapmaktır.
Aynı Dizin, Üç İç Düzen
Kurgu sunucunun /veri bölümünde ölçüm toplayıcı birimin ürettiği dosyalar tek bir dizinde
birikiyor. Dizin bir tablodur ve o tablonun iç düzeni bir tasarım kararıdır. İşletim Sistemi
Kavramları kursundaki dosya sistemi soyutlaması dersi bir dizini okumayı tek adım saymış
ve girdi sayısının adım sayısını değiştirmediğini varsaymıştı. Bu ders o varsayımın bedelini
ödüyor.
- DP8 — Ölçülen iş yeni bir dosya oluşturmaktır. Her oluşturma önce bir aramadır: aynı ad dizinde var mı. Sayılan şey bu aramadaki karşılaştırmalardır.
- DP9 — Sıralı liste düzeninde arama baştan sona gider. Karma tabanlı düzende ad bir kovaya düşer ve yalnız o kovadaki adlarla karşılaştırılır; kova sayısı 4096’dır ve biçimlendirme anında sabitlenmiştir. Ağaç düzeninde bir dal 200 ad taşır ve arama, ağacın derinliği kadar adımda biter.
- DP10 — Karşılaştırma sayısı ölçülür; gerçek zaman ölçülmez.
"""Dizin arama: ayni dosyalari tasiyan dizin , uc farkli ic duzen.""" KOVA = 4096 # karma tabanli dizindeki kova sayisi DAL = 200 # B-agaci dugumunun tasidigi ad sayisi def kurma_maliyeti(n, duzen): """Her yeni ad once ARANIR (var mi diye). Toplam karsilastirma.""" if duzen == "dogrusal": return n * (n - 1) // 2 if duzen == "karma": return sum(i // KOVA + 1 for i in range(n)) derinlik, toplam = 1, 0 for i in range(1, n + 1): if i > DAL ** derinlik: derinlik += 1 toplam += derinlik return toplam DUZEN = ("dogrusal", "karma", "agac") OLCEK = (1000, 5000, 10000, 30000, 100000) TABAN = {d: kurma_maliyeti(1000, d) for d in DUZEN} print("dosya sayisi ", " ".join(f"{d:>12s}" for d in DUZEN)) for n in OLCEK: print(f"{n:12d} ", " ".join(f"{kurma_maliyeti(n, d):12d}" for d in DUZEN)) print() print("1000 dosyadan dogrusal olceklenen tahmin ile gercek") print("dosya sayisi duzen tahmin gercek sapma kat yanlis tani") yanlis = 0 for n in OLCEK: for d in DUZEN: tahmin = TABAN[d] * n // 1000 gercek = kurma_maliyeti(n, d) kat = gercek / tahmin y = kat > 2 yanlis += y print(f"{n:12d} {d:10s} {tahmin:12d} {gercek:12d} {kat:10.2f} {str(y):>11s}") print("yanlis tani:", yanlis, "/", len(OLCEK) * len(DUZEN))
dosya sayisi dogrusal karma agac
1000 499500 1000 1800
5000 12497500 5904 9800
10000 49995000 17712 19800
30000 449985000 125312 59800
100000 4999950000 1271200 259800
1000 dosyadan dogrusal olceklenen tahmin ile gercek
dosya sayisi duzen tahmin gercek sapma kat yanlis tani
1000 dogrusal 499500 499500 1.00 False
1000 karma 1000 1000 1.00 False
1000 agac 1800 1800 1.00 False
5000 dogrusal 2497500 12497500 5.00 True
5000 karma 5000 5904 1.18 False
5000 agac 9000 9800 1.09 False
10000 dogrusal 4995000 49995000 10.01 True
10000 karma 10000 17712 1.77 False
10000 agac 18000 19800 1.10 False
30000 dogrusal 14985000 449985000 30.03 True
30000 karma 30000 125312 4.18 True
30000 agac 54000 59800 1.11 False
100000 dogrusal 49950000 4999950000 100.10 True
100000 karma 100000 1271200 12.71 True
100000 agac 180000 259800 1.44 False
yanlis tani: 6 / 15
Üç sayı yan yana. Kâhin: 30.000 dosyayı tek dizinde oluşturmak sıralı listede
449.985.000, karma tabanlı düzende 125.312, ağaç düzeninde 59.800
karşılaştırmadır. Araç çıktısı: üç dizin de ls ile aynı 30.000 adı verir ve dizin
girdisi sayısı her üçünde eşittir; iç düzen çıktıda yoktur. Yanlış tanı: küçük bir
dizinde ölçüp doğrusal ölçekleyen tahmin, on beş durumun altısında iki katından fazla
sapıyor.
Tabloda üstünlük yok, eğri farkı var. Bin dosyada ağaç düzeni karma düzenden pahalıdır (1800’e karşı 1000); yüz bin dosyada beş kat ucuzdur. Karma tabanlı düzenin de bir sınırı görünüyor: kova sayısı biçimlendirme anında sabitlendiği için zincirler uzuyor ve 100.000 dosyada maliyet doğrusal tahminin 12,71 katına çıkıyor. Sabitlenen her sayı, ölçek büyüdükçe ödenen bir borçtur.
Sağlama Toplamı Olan ve Olmayan Okuma
İkinci eksen okumanın doğruluğudur. Bir blok diskte kendiliğinden bozulabilir; yazıldığı gibi kalmadığı hâlde aygıt onu hatasız döndürür. Tasarım bunu sınamıyorsa bozulma sessizdir: uygulama yanlış baytı doğru sanır.
- DP11 — Ortak tanımın
/veridosya sistemi 30.000 dosya taşır ve her dosya bir blok tutar. Dosya düğümü tablosu 2048 bloktur; bir bloğa 16 dosya düğümü sığar. - DP12 — Bir dosyayı okumak iki bloğa dokunur: kendi veri bloğu ve dosya düğümünün bulunduğu tablo bloğu.
- DP13 — 40 blok bozulur; hangileri olduğu üreteçle seçilir. Sağlama taşıyan bir tasarım bozulmayı okuma anında yakalar, taşımayan yakalamaz.
"""Saglama toplami: bozulan blok okuma sirasinda yakalaniyor mu.""" TOHUM = 20260218 BLOK = 4096 DOSYA = 30000 # ortak tanimin /veri dosya sistemi DUGUM_BLOKTA = 16 # 4096 baytlik bloga 16 dosya dugumu (256 bayt) META = 2048 # 32768 dugumluk tablo , blok cinsinden BOZUK = 40 def uretec(tohum): d = tohum def sonraki(n): nonlocal d d = (d * 1103515245 + 12345) % 2147483648 return d % n return sonraki def bozulanlar(tohum=TOHUM, adet=BOZUK, veri=DOSYA, meta=META): """Kahin: hangi bloklar gercekten bozuldu. Ilk `veri` tanesi veri blogu.""" r = uretec(tohum) return {r(veri + meta) for _ in range(adet)} def okuma(tasarim, bozuk, veri=DOSYA): """Her dosya kendi veri blogunu ve dugum tablosundaki blogunu okur.""" veri_saglama, meta_saglama = tasarim yakalanan = sessiz = 0 for i in range(veri): vb = i in bozuk mb = (veri + i // DUGUM_BLOKTA) in bozuk if (vb and veri_saglama) or (mb and meta_saglama): yakalanan += 1 elif vb or mb: sessiz += 1 return {"yakalanan": yakalanan, "sessiz": sessiz} TASARIM = {"saglama yok": (False, False), "meta saglamali": (False, True), "veri+meta saglamali": (True, True)} B = bozulanlar() print("bozulan blok:", len(B), "| veri blogu:", sum(1 for x in B if x < DOSYA), "| meta veri blogu:", sum(1 for x in B if x >= DOSYA)) print("kahin: bozuk bloga dokunan okuma:", okuma((True, True), B)["yakalanan"], "/", DOSYA) print() print("tasarim hatayla donen sessizce bozuk donen yanlis tani") for ad, t in TASARIM.items(): o = okuma(t, B) print(f" {ad:20s} {o['yakalanan']:13d} {o['sessiz']:20d} {o['sessiz']:11d}") ek = -(-(DOSYA + META) * 4 // BLOK) print("saglama toplami deposu:", ek, "blok |", round(ek / (DOSYA + META) * 100, 3), "yuzde") print() for tohum in (TOHUM, 20260219): b2 = bozulanlar(tohum) print(f"tohum {tohum}: saglamasiz sessiz {okuma((False, False), b2)['sessiz']:4d}" f" meta saglamali {okuma((False, True), b2)['sessiz']:4d}" f" tam saglamali {okuma((True, True), b2)['sessiz']:4d}")
bozulan blok: 40 | veri blogu: 38 | meta veri blogu: 2 kahin: bozuk bloga dokunan okuma: 54 / 30000 tasarim hatayla donen sessizce bozuk donen yanlis tani saglama yok 0 54 54 meta saglamali 16 38 38 veri+meta saglamali 54 0 0 saglama toplami deposu: 32 blok | 0.1 yuzde tohum 20260218: saglamasiz sessiz 54 meta saglamali 38 tam saglamali 0 tohum 20260219: saglamasiz sessiz 70 meta saglamali 38 tam saglamali 0
Üç sayı yan yana. Kâhin: 40 blok bozuldu ve bunlara dokunan okuma sayısı 54’tür — 38 dosya kendi veri bloğundan, 16 dosya iki bozuk tablo bloğundan etkileniyor. Araç çıktısı: sağlama taşımayan tasarımda okuma çağrılarının hepsi hatasız dönüyor; hiçbir araç bir şey bildirmiyor. Yanlış tanı: o tasarımda 54 okuma bozuk baytı doğru sanıyor; meta veri sağlaması eklendiğinde 38’e iniyor, veri de sağlandığında sıfır oluyor.
Bedeli tabloda: 32.048 bloğun sağlama 32 blok yer tutuyor, yani yüzde 0,1. Yer maliyeti küçük, işlem maliyeti ise her okumaya eklenen bir hesaptır ve bu ders onu saymaz. İkinci tohumda bozuk blok dağılımı değişiyor, sessiz okuma 54 yerine 70 çıkıyor; sıralama değişmiyor. Sayının kendisi kurguya bağlı, sıfırla arasındaki fark değil.
Buradaki asıl sonuç şudur: sağlama olmayan bir tasarımda “hata yok” çıktısı, “veri doğru” demek değildir. Bozulma ancak bir tutarlılık denetimi çalıştırıldığında ya da veri kullanıldığında ortaya çıkar; ikisi de okumadan sonradır. Kursun üçüncü iddiası burada da işliyor — geç bakan az görür.
Tutarlılık denetimi de bedava değildir ve ne yaptığına dikkat etmek gerekir. fsck sınıfı
araçlar defterleri baştan sona gezip birbirleriyle uyumlu olup olmadıklarına bakar; buldukları
uyumsuzluğu onararak çıkarlar ve onarım bazen bir dosyayı sahipsiz kayıtların toplandığı
bir dizine taşımak demektir. Bu iş takılı bir dosya sisteminde yapılamaz: araç çalışırken
dosya sistemi değişmemelidir, aksi hâlde araç kendi okuduğu defteri geçersiz kılar. Bu yüzden
takılı bir dosya sisteminde onarım komutu çalıştırılabilir tam biçimde verilmez; sınama,
dosya sistemi ayrıldıktan sonra ya da yalnız rapor üreten seçenekle yapılır.
Denetimin bulabildiği şeyin sınırı da vardır. Defterler arası uyumsuzluk bulunur; bir veri bloğunun içeriğinin değişmiş olduğu bulunamaz, çünkü doğru içeriğin ne olduğunu söyleyen bir kayıt yoktur. Tabloda sağlamanın satın aldığı şey tam olarak budur: doğru içeriğin ne olduğunu bilmeye değil, yanlış olduğunu anlamaya yarayan 32 bloklu bir kayıt.
Özet
- Bir dosya sistemi ad defteri, meta veri defteri, alan defteri ve tutarlılık defterini aynı bölümde tutar; aileler arasındaki fark bu dört defterin nasıl tutulduğudur, bir üstünlük sıralaması değildir.
- 30.000 dosyayı tek dizinde oluşturmak sıralı listede 449.985.000, karma tabanlı düzende
125.312, ağaç düzeninde 59.800 karşılaştırmadır; üç dizin de
lsile aynı listeyi verir. - Küçük bir dizinde ölçüp doğrusal ölçekleyen tahmin on beş durumun altısında iki katından fazla sapıyor; karma düzende kova sayısının biçimlendirme anında sabitlenmesi 100.000 dosyada tahmini 12,71 kat aşırıyor.
- Sağlama taşımayan tasarımda bozuk bloğa dokunan 54 okumanın 54’ü hatasız dönüyor; meta veri sağlamasıyla 38, veri sağlamasıyla 0 oluyor. Depolama bedeli 32 blok, yüzde 0,1.
- Biçimlendirme anında sabitlenen her sayı bir tavandır; bir sonraki ders o tavanlardan birine çarpmanın ne göründüğünü ölçer.
Sonraki Adım
Bu ders meta veri defterini bir tasarım ekseni olarak saydı ama içine bakmadı: bir dosyanın adı dışındaki her şeyini taşıyan kaydın kendisi bir kaynaktır ve tükenebilir. Sonraki ders o kaydı ölçer ve kursun en çarpıcı sayısını çıkarır — aynı dosya sisteminde blok doluluk 0,0125 iken yazma başarısız oluyor. Disk yüzde bir dolu ve sistem dolu; doluluk yüzdesine bakan tanı burada kesinlikle yanılıyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.