Ders 16 / 22
Blok Aygıtları ve Bölümler
Bölüm listesi bir harita değildir: aygıtta 3.702.784 boş sektör görünürken en büyük bitişik boşluk 2.881.536 sektördür ve listeden çıkarılan on iki yerleştirme kararının altısı yanlış çıkar.
İçindekiler
Günlükler konusu bir darboğazın hangi göstergeden okunacağını ayırdı ve girdi/çıktı beklemesini bir sayıya indirdi. O sayının altında bir aygıt duruyor ve bu konu oraya iniyor: baytların gerçekten yazıldığı yere. Depolama, sistem yönetiminde arızanın en sessiz göründüğü katmandır; bir sürecin durduğu görülür, bir servisin çalışmadığı görülür, ama bir diskin dolduğu çoğu zaman ancak yazma başarısız olduğunda görülür.
İlk soru en alttakidir. Bir dosya sistemi aygıtın tamamına değil, aygıtın bir parçasına kurulur; o parçanın nerede başlayıp nerede bittiğini küçük bir tablo söyler. Bu ders o tabloyu okur ve tablonun söylemediği şeyi sayar.
Aygıt, Sektör ve Bölüm
Blok aygıtı (block device), sabit boyutlu birimler hâlinde okunup yazılan bir depolama birimidir. En küçük adreslenebilir birime sektör denir; aygıt, sıfırdan başlayarak numaralanmış sektörlerin bir dizisidir ve bu dizinin dışında bir yapısı yoktur. İçindeki düzenin tamamı, aygıtın ilk sektörlerinde duran bir veri yapısından okunur.
Sektörün iki boyutu vardır ve ikisi aynı olmak zorunda değildir. Aygıtın dışarıya gösterdiği mantıksal sektör ile içeride gerçekten tek seferde okunup yazılan fiziksel sektör ayrı sayılardır; yaygın kurulumda mantıksal sektör 512 bayt, fiziksel sektör 4096 bayttır. Yani aygıt 512 baytlık adresler kabul eder ama 512 bayt yazmak istendiğinde 4096 baytlık bir bloğu okuyup değiştirip geri yazar. Bu ayrım hizalama bölümünde sayılacak farkın kaynağıdır ve bölümleme tablosunun hiçbir yerinde durmaz; aygıtın kendi bildirimidir.
O veri yapısı bölümleme tablosudur (partition table). Tablo, her bölüm (partition) için başlangıç sektörünü, bitiş sektörünü ve bir tür etiketini tutar. Tablonun tuttuğu şey budur ve bundan fazlası değildir: bölümün içinde ne olduğunu, dolu mu boş mu olduğunu, hatta içinde bir dosya sistemi bulunup bulunmadığını tablo bilmez. Bir bölüm, aygıtın gövdesine çizilmiş bir aralıktan ibarettir.
İki tablo biçimi yaygındır. Eski biçim dört birincil bölümle sınırlıdır ve fazlasını ancak bir bölümün içine iç içe girdiler koyarak taşır; sonraki biçim yüzlerce girdiye izin verir, her bölüme değişmez bir kimlik verir ve tablonun bir kopyasını aygıtın sonunda tutar. Aradaki fark bir üstünlük sıralaması değil, bir kapasite farkıdır ve hangisinin kullanıldığı aygıtın kendisine bakılarak öğrenilir.
Bölümleri listeleyen araçlar okuma yapar ve tehlikesizdir: lsblk aygıt ağacını verir,
blkid bölümlerin kimliklerini ve tür etiketlerini yazar, parted sektör biriminde bir
tablo döker. Aşağıdaki döküm parted çıktısının biçimini gösteren bir örnek dökümdür;
çalıştırılmamıştır ve bu derste hiçbir sayı iddiası buradan gelmez.
Model: kurgu blok aygiti Disk /dev/sdb: 12582912s Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name 1 2048s 1048575s 1046528s ext4 kok 2 1048576s 3344383s 2295808s ext4 veri 3 3753984s 4636671s 882688s ext4 gunluk 4 4636672s 6383615s 1746944s linux-swap takas
Dökümde dikkat çeken şey, dördüncü satırın bittiği yer ile bir sonraki bölümün başladığı yer arasındaki boşluğun yazılmamış olmasıdır. Araç bölümleri listeler; aralarda kalanı listelemez.
Neden Bölümlenir
Bir aygıta tek bir dosya sistemi kurmak da bir seçenektir ve bölümleme onun karşısındaki seçenektir. Ayrımın gerekçesi kapasite değil, arızanın yayılmasını sınırlamaktır. Kurgu sunucuda günlük yazan birimler ile ölçüm dosyası üreten birimler aynı aygıtı paylaşıyor; ikisi de aynı dosya sistemine yazarsa, günlük döndürme bir kez aksadığında dolan alan yalnız günlükleri değil, kök dosya sistemini de doldurur ve sistem oturum açamayacak duruma gelir. Ayrı bölüm, dolmayı kendi sınırının içinde tutar.
İkinci gerekçe farklı takma seçenekleridir: bir bölüm salt okunur, bir başkası program çalıştırmaya kapalı takılabilir. Üçüncüsü, bir bölümün dosya sistemi türünün diğerinden bağımsız seçilebilmesidir. Bedeli de vardır ve ölçülebilir: her bölümün boşluğu yalnız kendisine yarar. Yukarıdaki yerleşimde günlük bölümü dolarken ayrılmış bölümde 1.320.960 sektörlük yer boş durabilir ve bu iki sayı birbirine aktarılamaz. Bölümleme, esneklikten vazgeçip yalıtım satın alır; sonraki derslerden biri bu ödünleşmeyi gevşeten bir katmanı ölçecek.
Bölüm Listesi Bir Harita Değildir
Bölüm listesinden boş alan hesaplamanın tek yolu çıkarma işlemidir: aygıtın sektör sayısından bölümlerin toplamı düşülür. Bu işlem doğru bir toplam verir ve yanlış bir tanı üretir, çünkü boş alan tek parça değildir.
- DP1 — Kurgu aygıt 12.582.912 sektörlüktür; bütün ölçüler sektör cinsindendir ve hiçbir gerçek aygıtın boyutu yazılmaz.
- DP2 — Bölümler 2048 sektörlük bir kata hizalanır. İlk 2048 sektör bölümleme tablosuna ayrılmıştır ve bölüm olarak kullanılamaz.
- DP3 — Yerleşim, ortak tanımın üretecinden 20260218 tohumuyla üretilir; altı bölüm kurgu sunucunun kök, veri, günlük, takas, yedek ve ayrılmış alanlarını taşır.
- DP4 — Araç çıktısı bölüm listesidir; boşluk haritası çıktıda yoktur. Tanı yalnız listeden kurulur.
- DP5 — Bir yerleştirme kararı iki sorudan oluşur: istenen boyut sığar mı ve o boyuttan kaç tane sığar.
"""M03/K03 depolama: kurgu blok aygitinin bolum yerlesimi ve bosluk haritasi.""" TOHUM = 20260218 HIZA = 2048 # bolumler bu sektor katinda baslar AYGIT = 12582912 # kurgu aygitin sektor sayisi AD = ("kok", "veri", "gunluk", "takas", "yedek", "ayrilmis") def uretec(tohum): d = tohum def sonraki(n): nonlocal d d = (d * 1103515245 + 12345) % 2147483648 return d % n return sonraki def yerlesim(tohum=TOHUM): """Kahin: bolumlerin gercek baslangici ve boyutu , sektor cinsinden.""" r = uretec(tohum) b, imlec = [], HIZA for ad in AD: boyut = (r(900) + 300) * HIZA b.append({"ad": ad, "bas": imlec, "boyut": boyut}) imlec += boyut + r(4) * 100 * HIZA return b def bosluklar(b, aygit=AYGIT): """Kahin: bolumler arasinda ve sonda kalan BITISIK bos araliklar.""" g, imlec = [], 0 for x in sorted(b, key=lambda z: z["bas"]): if x["bas"] > imlec: g.append(x["bas"] - imlec) imlec = x["bas"] + x["boyut"] if imlec < aygit: g.append(aygit - imlec) return g def tani(b, istek, aygit=AYGIT): """Arac ciktisi bolum LISTESIDIR. Listeden cikarilan tani: bos alan , aygit eksi bolumlerin toplami.""" g = bosluklar(b, aygit) toplam_bos = aygit - sum(x["boyut"] for x in b) yanlis, satir = 0, [] for s in istek: arac_sigar, gercek_sigar = s <= toplam_bos, s <= max(g) arac_adet, gercek_adet = toplam_bos // s, sum(x // s for x in g) yanlis += (arac_sigar != gercek_sigar) + (arac_adet != gercek_adet) satir.append((s, arac_sigar, gercek_sigar, arac_adet, gercek_adet)) return {"toplam_bos": toplam_bos, "en_buyuk": max(g), "bosluk": len(g), "satir": satir, "yanlis": yanlis} B = yerlesim() print("bolum baslangic boyut bitis") for x in B: print(f" {x['ad']:9s} {x['bas']:9d} {x['boyut']:9d} {x['bas'] + x['boyut']:11d}") print("kullanilan sektor:", sum(x["boyut"] for x in B), "| bos sektor:", AYGIT - sum(x["boyut"] for x in B)) print("bitisik bosluk sayisi:", len(bosluklar(B)), "| bosluklar:", bosluklar(B)) print() ISTEK = (204800, 614400, 1228800, 2457600, 3072000, 3686400) print("istenen arac: sigar gercek: sigar arac: adet gercek: adet") for s, a, ge, aa, ga in tani(B, ISTEK)["satir"]: print(f"{s:7d} {str(a):11s} {str(ge):13s} {aa:10d} {ga:12d}") print() for tohum in (TOHUM, 20260219): t2 = tani(yerlesim(tohum), ISTEK) print(f"tohum {tohum}: bos {t2['toplam_bos']:8d} en buyuk bitisik {t2['en_buyuk']:8d}" f" bosluk {t2['bosluk']:2d} yanlis tani {t2['yanlis']:2d} / 12")
bolum baslangic boyut bitis kok 2048 1046528 1048576 veri 1048576 2295808 3344384 gunluk 3753984 882688 4636672 takas 4636672 1746944 6383616 yedek 6793216 1587200 8380416 ayrilmis 8380416 1320960 9701376 kullanilan sektor: 8880128 | bos sektor: 3702784 bitisik bosluk sayisi: 4 | bosluklar: [2048, 409600, 409600, 2881536] istenen arac: sigar gercek: sigar arac: adet gercek: adet 204800 True True 18 18 614400 True True 6 4 1228800 True True 3 2 2457600 True True 1 1 3072000 True False 1 0 3686400 True False 1 0 tohum 20260218: bos 3702784 en buyuk bitisik 2881536 bosluk 4 yanlis tani 6 / 12 tohum 20260219: bos 3633152 en buyuk bitisik 1787904 bosluk 7 yanlis tani 6 / 12
Üç sayı yan yana. Kâhin: boş alan dört parçadır — 2048, 409.600, 409.600 ve 2.881.536 sektör; en büyük bitişik aralık 2.881.536 sektördür. Araç çıktısı: bölüm listesi, toplamı 8.880.128 sektör olan altı satır; buradan çıkarılan boş alan 3.702.784 sektör. Yanlış tanı: on iki karardan altısı yanlış.
Yanlışların dağılımı da öğreticidir. İki karar “sığar” derken sığmıyor: 3.072.000 ve 3.686.400 sektörlük bölümler toplam boş alanın altında kalıyor ama hiçbir bitişik aralığa girmiyor. Dört karar ise adette yanılıyor: araç 614.400 sektörlük altı bölüm sığdığını söylüyor, gerçekte dördü sığıyor. Toplam doğru, tanı yanlış.
İkinci tohumla üretilen yerleşimde boş alan 3.633.152 sektöre, en büyük bitişik aralık 1.787.904 sektöre iniyor ve boşluk sayısı yediye çıkıyor; yanlış tanı yine 6. Sayının aynı kalması rastlantıdır, aynı büyüklük düzeninde kalması değil: boşluk sayısı arttıkça toplamdan çıkarılan tanı bozulmaya devam ediyor.
Hizalama
Bölümün nerede başladığı, içine kurulacak dosya sisteminin başarımını belirler. Dosya sistemi 4096 baytlık bloklarla çalışır ve bir blok sekiz sektördür; aygıtın kendi fiziksel bloğu da sekiz sektördür ve sıfırdan itibaren sayılır. Bölüm sekizin katı olmayan bir sektörde başlarsa, dosya sisteminin her bloğu iki fiziksel bloğa yayılır.
- DP6 — Sıralı yazmada dokunulan fiziksel blok sayısı, hizasızlıkta yalnız bir artar; bloklar zaten peş peşedir.
- DP7 — Rastgele tek blok yazmada hizasız bir blok iki fiziksel bloğa dokunur ve ikisinin de değişmeyen bölümü korunmak zorunda olduğu için önce okunup sonra yazılır: dört işlem.
"""Hizalama: dosya sistemi blogu ile aygit blogu ayni sinira oturuyor mu.""" SEKTOR_BLOKTA = 8 # 4096 baytlik blok , 512 baytlik 8 sektor BLOK_SAYISI = 512 # yazilan dosya sistemi blogu BOLUM_BOYUTU = 1048576 # alti yerlesimde de ayni , sektor def maliyet(bas, blok=BLOK_SAYISI, s=SEKTOR_BLOKTA): kayma = bas % s return {"hizali": kayma == 0, "sirali": blok + (1 if kayma else 0), "rastgele": blok * (4 if kayma else 1)} print("baslangic bolum boyutu hizali sirali islem rastgele islem") yanlis = 0 for bas in (63, 2048, 2049, 2052, 2056, 4096): m = maliyet(bas) yanlis += not m["hizali"] print(f"{bas:9d} {BOLUM_BOYUTU:12d} {str(m['hizali']):6s}" f" {m['sirali']:12d} {m['rastgele']:14d}") print("arac ciktisindaki bolum boyutu alti yerlesimde de ayni:", BOLUM_BOYUTU) print("bu boyuttan cikarilan 'ayni yerlesim' tanisi kac kez yanlis:", yanlis, "/ 6")
baslangic bolum boyutu hizali sirali islem rastgele islem
63 1048576 False 513 2048
2048 1048576 True 512 512
2049 1048576 False 513 2048
2052 1048576 False 513 2048
2056 1048576 True 512 512
4096 1048576 True 512 512
arac ciktisindaki bolum boyutu alti yerlesimde de ayni: 1048576
bu boyuttan cikarilan 'ayni yerlesim' tanisi kac kez yanlis: 3 / 6
Altı yerleşimin bölüm boyutu aynıdır ve araç çıktısında bu boyut görünür; başlangıç sektörü de görünür ama okunmaz, çünkü bir sayının sekize bölünüp bölünmediği listeye bakılırken sorulmaz. Sıralı yazmanın maliyeti hizasızlıkta 512’den 513’e çıkıyor, yani ölçülemez bir fark; rastgele yazmanınki 512’den 2048’e çıkıyor. Sıralı bir sınamayla verilen “fark yok” tanısı, altı yerleşimin üçünde yanlıştır. Bu, kursun ikinci iddiasının depolamadaki karşılığıdır: sınamayı çoğaltmak değil, doğru yükü sınamak ayırır.
Tablodaki 2056 satırı, hizalamanın 2048’e özgü olmadığını gösteriyor: sekizin katı olan her
başlangıç hizalıdır. Bölümleme araçlarının 2048 sektörü öntanımlı seçmesinin nedeni sekiz
değil, çok daha büyük iç birimlerle çalışan aygıtlarda da hizalı kalmaktır; 2048, olası iç
birim boylarının hepsine bölünen bir sayıdır. Araçlar bu kararı sessizce almaz, uyarı da
üretirler ve lsblk hizalama sapmasını ayrı bir sütunda yazar. Uyarı çıktıda durur; okunması
bir alışkanlık meselesidir ve okunmadığında ortaya çıkan fark, ölçüldüğü ana kadar hiçbir
yerde görünmez.
Bölümleme Tablosunu Değiştirmek
Tabloyu okuyan araçlar tehlikesizdir; yazan araçlar geri alınamaz. Bir bölümü silmek veya sınırını değiştirmek, tablodaki başlangıç ve bitiş değerlerini üzerine yazar; bölümün içindeki veri silinmez ama ona nasıl ulaşılacağı bilgisi kaybolur ve tablo yeniden yazılmadan içerik erişilebilir hâle gelmez. Bu yüzden tablo yazan komutlar bu derste çalıştırılabilir tam biçimde verilmez.
Değişiklik zorunluysa üç önlem ölçülebilir bir güvenlik sağlar. Birincisi, tablonun metin
biçiminde dökümünü almaktır; sfdisk --dump gibi bir okuma komutu tabloyu bir dosyaya
yazar ve aynı dosya geri yüklenerek eski yerleşim kurulabilir. İkincisi kuru çalışmadur:
tablo yazan araçların çoğu, değişikliği uygulamadan sonucu gösteren bir seçenek taşır ve bu
seçenek çalıştırılmadan önce çıktının okunması gerekir. Üçüncüsü, denemenin ayrı bir
aygıtta yapılmasıdır; bir dosyayı geri döngü aygıtı (loop device) olarak bağlamak, bölümleme
alıştırmasını gerçek veriden uzakta yapmayı sağlar.
Bir de sıralama kuralı vardır: tabloyu değiştiren bir komut döndüğünde çekirdek eski
yerleşimi bellekte tutuyor olabilir. Bu durumda lsblk yeni tabloyu gösterirken takılı
dosya sistemleri eski sınırlarla çalışmaya devam eder. Komutun dönmesi değişikliğin
geçtiği anlamına gelmez; bu, süreç yönetimi konusunda sinyaller için kurulan cümlenin
depolamadaki eşidir.
Özet
- Blok aygıtı numaralanmış sektörlerin bir dizisidir; içindeki düzenin tamamı, ilk sektörlerde duran bölümleme tablosundan okunur ve tablo yalnız başlangıç, bitiş ve tür bilgisini taşır.
- Bölüm listesinden çıkarılan boş alan bir toplamdır, harita değildir: 3.702.784 boş sektörün en büyük bitişik parçası 2.881.536 sektördür ve boş alan dört parçaya bölünmüştür.
- On iki yerleştirme kararının altısı yalnız listeye bakıldığında yanlış çıkıyor; ikisi sığmayanı sığar sanıyor, dördü sığan adedini fazla sayıyor. İkinci tohumda boşluk sayısı yediye çıkıyor ve yanlış tanı yine 6 oluyor.
- Bölüm başlangıcının sekiz sektörün katı olması sıralı yazmada 512 yerine 513 işlem farkı üretiyor, rastgele yazmada 512 yerine 2048; aynı bölüm boyutunu gösteren çıktıdan çıkarılan “fark yok” tanısı altı yerleşimin üçünde yanlış.
- Bölümleme tablosunu yazan komutlar geri alınamaz; ölçülebilir üç önlem tablonun dökümünü almak, kuru çalışma seçeneğini okumak ve denemeyi ayrı bir aygıtta yapmaktır.
Sonraki Adım
Bu ders bölümün içine hiç bakmadı: tablo için bir bölüm, başlangıcı ve bitişi olan bir aralıktan ibaretti. Oysa o aralığa bir dosya sistemi kurulduğu anda, bir daha kolay değiştirilemeyecek kararlar alınır — kaç dosya tutulabileceği, meta verinin ne kadar yer kaplayacağı ve okunan verinin bozulmuşsa fark edilip edilmeyeceği. Sonraki ders dosya sistemi ailelerinin bu kararları nasıl farklı verdiğini ölçer ve sağlama taşımayan bir tasarımın bozuk veriyi kaç kez sessizce döndürdüğünü sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.