İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat