Bölüm 15: İşletim Sistemi Tasarımı

Bölüm 15: İşletim Sistemi Tasarımı · Çalışma Soruları
HedeflerArayüz tasarımıSistem yapısıTasarım ilkeleriYararlı tekniklerPerformansProje yönetimiTest ve hata ayıklamaEğilimler
Sercan KÜLCÜ

Çoktan Seçmeli · Hedefler

Soru 1: Hangisi Temel Hedef Değil?

Bir işletim sisteminin temel hedefleri soyutlama tanımlamak, ilkel işlemler sağlamak, yalıtım sağlamak ve donanımı yönetmektir. Hangisi bu hedeflerden biri değildir?

B: derleme bir araç zincirinin (derleyici) işidir; işletim sistemi derlenmiş programı yükler ve çalıştırır. A donanım yönetimi, C soyutlama, D yalıtım hedefidir; ilkel işlemler ise bu soyutlamalar üzerindeki sistem çağrılarıdır.

Çoktan Seçmeli · Arayüz İlkeleri

Soru 2: Hangi İlke?

“Programcı bir sistem çağrısının yaklaşık maliyetini sezebilmelidir; ucuz görünen bir çağrı gizlice pahalı olmamalıdır. İyi gerçekleştirilemeyen bir özellik muhtemelen eklenmeye değmez.” Bu cümle arayüz tasarımının hangi ilkesini anlatır?

D: arayüz ilkeleri basitlik (az ama iyi düşünülmüş kavram), bütünlük (gereken her şey yapılabilmeli) ve verimliliktir. Örnek: lseek yalnız bir sayıyı değiştirir ve ucuzdur, read ise disk erişimi gerektirebilir. Geriye dönük uyumluluk ise yayımlanmış çağrıların kaldırılamaması demektir; bir kısıttır.

Adım Adım Çalıştırma · Olay Güdümlü Kod

Soru 3: Olay Döngüsünün Sonucu

Uygulamanın kuyruğuna olaylar şu sırayla geliyor: KEY CLICK KEY TIMER CLICK KEY KEY QUIT. Program ne yazdırır?

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =0

Program başlar; kuyrukta sekiz olay var. Akışı program değil, olayların sırası belirler.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =1

KEY: n bir artar → 1.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =11

CLICK: n 10 artar → 11.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =12

KEY: n bir artar → 12.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =0

TIMER: n = 12 > 10, sıfırlanır.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =10

CLICK: n 10 artar → 10.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =11

KEY: n bir artar → 11.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =12

KEY: n bir artar → 12.

olay kuyruğuKEYCLICKKEYTIMERCLICKKEYKEYQUITn =12

QUIT: get_message 0 döndürür, döngü biter; 12 yazılır. Uzun süren bir işleyici kuyruktaki tüm olayları bekletir, arayüz donar.

int n = 0;
msg_t m;
while (get_message(&m)) {     /* QUIT → 0 */
    switch (m.type) {
    case KEY:   n++;               break;
    case CLICK: n += 10;           break;
    case TIMER: if (n > 10) n = 0; break;
    }
}
printf("%d\n", n);

Çoktan Seçmeli · Mikro Çekirdek

Soru 4: Mikro Çekirdeğin Ödünleşimi

Bir ekip ağ sürücüsünü çekirdekten çıkarıp kullanıcı alanında ayrı bir sunucu süreci olarak çalıştırmaya karar veriyor. Tipik kazanç ve bedel hangisidir?

A: işletim sistemi tasarımının temel ödünleşimlerinden biri performans ile yalıtım arasındadır. Kullanıcı alanındaki sürücü hatası tüm sistemi düşürmez (MINIX 3 onu yeniden başlatır); ama her paket IPC, bağlam değiştirme ve kopyalama maliyeti öder.

Çoktan Seçmeli · Exokernel

Soru 5: Exokernel ile Sanal Makine

Exokernel’i sanal makine monitöründen (hipervizör) ayıran temel fark hangisidir?

C: exokernel blokları, sayfaları, zaman dilimlerini bölüştürüp kimin neye sahip olduğunu izler; dosya ve süreç gibi soyutlamalar libOS’tadır, yeniden eşleme katmanı gerekmez. Makinenin kopyasını veren hipervizördür (A ters). Bileşenleri çalışırken yüklemek genişletilebilir sistemlerin özelliğidir.

Çoktan Seçmeli · Mekanizma ve Politika

Soru 6: Mekanizma mı, Politika mı?

Hangisi bir politikadır (mekanizma değil)?

D: mekanizma “nasıl yapılır”ı, politika “neyin yapılacağına karar”ı belirler. Sayfa yer değiştirme kuralı (LRU, saat…) politikadır; MMU, bağlam değiştirme ve LSM kancaları politikadan bağımsız mekanizmalardır (SELinux kuralları ise LSM’nin politikasıdır).

Hesaplama Sorusu · Adlandırma

Soru 7: Yol Çözümleme Maliyeti

open("/home/ali/ders/notlar.txt") çağrısında her dizin tek bir bloğa sığıyor. (a) Hiçbir şey önbellekte değilken dosyanın i-node’una ulaşmak için kaç disk okuması gerekir? (b) Ad önbelleğinde /home/ali → i-node eşlemesi ve o i-node bellekteyse?

Cevabı göster

Her dizin için önce i-node’u (verisinin yeri), sonra dizin bloğu (ad → i-node numarası) okunur.

(a) kök i-node + kök bloğu, home i-node + bloğu, ali i-node + bloğu, ders i-node + bloğu, sonda notlar.txt’nin i-node’u: 2 + 2 + 2 + 2 + 1 = 9 okuma.

(b) Arama ali’den sürer: ali’nin bloğu, ders i-node’u, ders bloğu, notlar.txt i-node’u = 4 okuma. Kısmi isabet bile kazançtır; Linux’ta bu iş dcache’indir. Yalnız dizin bloklarını saymak ya da dosyanın i-node’unu unutmak sık hatadır.

Çıktı Sorusu · Statik ve Dinamik Yapılar

Soru 8: Statik Tabloda Arama

Süreç tablosu derleme zamanında 6 girişlik sabit bir dizi; boş girişlerin pid’i 0. Program ne yazdırır? Tablo dolarsa ne olur?

struct proc { int proc_pid; };
struct proc proc_table[6]; /* 1 314 0 0 42 7 */

int ara(int pid) {
    int n = 0;
    struct proc *p;
    for (p = proc_table; p < proc_table + 6; p++) {
        n++;
        if (p->proc_pid == pid) return n;
    }
    return -n;
}
/* main: */
printf("%d %d %d\n", ara(42), ara(7), ara(99));
Cevabı göster

Çıktı: 5 6 -6

  • 42 beşinci girişte: 5 karşılaştırma. 7 son girişte: 6. 99 yok: tüm tablo tarandı, −6.
  • p++ bir sonraki yapıya ilerler (bayta değil); boş girişler de tek tek taranır: O(n).
  • Statik tablo basittir, bellek ayırıcı gerektirmez; ama dolunca yeni süreç oluşturulamaz (eski UNIX’te NPROC). Dinamik yapılar (hash tablosu, xarray) bu sınırı kaldırır; bedeli ayırıcı, parçalanma ve karmaşık kilitlemedir.

Çıktı Sorusu · Donanımı Gizleme

Soru 9: Koşullu Derleme

Kod 64 bit Linux (LP64) için derleniyor; init() ne yazdırır? Yeni bir işlemciye taşırken hangi kısım değişir?

#define X86_64 1
#define ARM64  2
#define CPU    ARM64
#define WORD_LENGTH 64

#if (WORD_LENGTH == 32)
typedef int Register;
#elif (WORD_LENGTH == 64)
typedef long Register;
#endif

void init(void) {
#if (CPU == X86_64)
    puts("x86-64 başlatma");
#endif
#if (CPU == ARM64)
    puts("ARM64 başlatma");
#endif
    printf("%zu\n", sizeof(Register));
}
Cevabı göster

Çıktı: ARM64 başlatma ve 8

  • Önişlemci yalnız koşulu doğru olan satırları derlemeye bırakır: CPU = 2 olduğu için x86-64 bloğu derlenmez bile.
  • WORD_LENGTH 64 → Register = long; LP64’te long 8 bayttır. (64 bit Windows’ta long 4 bayttır: taşınabilir kodda uintptr_t tercih edilir.)
  • Taşırken yalnız config.h ve donanıma bağlı dosyalar değişir (Linux’ta arch/ dizinleri, Windows’ta HAL). Her yere dağılmış #if kodu okunmaz hâle getirir.

Çoktan Seçmeli · Yeniden Girişlilik

Soru 10: Yeniden Girişli mi?

strtok kaldığı konumu içindeki bir static char * değişkende saklar. İki iş parçacığı aynı anda farklı dizgileri strtok ile parçalarsa ne olur?

B: static değişken yığında değil, tüm iş parçacıklarının paylaştığı veri kesimindedir. Yeniden girişli kod aynı anda iki kez çalışabilmeli (iki iş parçacığı ya da aynı fonksiyonu çağıran bir kesme işleyicisi): paylaşılan statik durum yok; gerekirse durum parametreyle taşınır ya da kilitle korunur.

Adım Adım Çalıştırma · Uzay-Zaman Ödünleşimi

Soru 11: Bit Sayma Döngüsü

bit_count(0x9D) ne döndürür? Aynı sonucu tek bellek okumasıyla verecek tablo kaç bayttır?

byte = 0x9D1b70b60b51b41b31b20b11b0count =0

0x9D = 1001 1101. Her turda bayt i bit sağa kaydırılır, en düşük bit 1 ile maskelenir.

byte = 0x9D1b70b60b51b41b31b20b11b0count =1

(byte >> 0) & 1 = 1: count artar.

byte = 0x9D1b70b60b51b41b31b20b11b0count =1

(byte >> 1) & 1 = 0: dal alınmaz.

byte = 0x9D1b70b60b51b41b31b20b11b0count =2

(byte >> 2) & 1 = 1: count artar.

byte = 0x9D1b70b60b51b41b31b20b11b0count =3

(byte >> 3) & 1 = 1: count artar.

byte = 0x9D1b70b60b51b41b31b20b11b0count =4

(byte >> 4) & 1 = 1: count artar.

byte = 0x9D1b70b60b51b41b31b20b11b0count =4

(byte >> 5) & 1 = 0: dal alınmaz.

byte = 0x9D1b70b60b51b41b31b20b11b0count =4

(byte >> 6) & 1 = 0: dal alınmaz.

byte = 0x9D1b70b60b51b41b31b20b11b0count =5

(byte >> 7) & 1 = 1: count artar.

byte = 0x9D1b70b60b51b41b31b20b11b0count =5

Döngü 8 tur döndü: 5 döner. 256 girdilik char bits[256] tablosu aynı sonucu tek bellek okumasıyla verir: 256 B yer harcayıp zaman kazanmak.

int bit_count(int byte) {
    int i, count = 0;
    for (i = 0; i < 8; i++)
        if ((byte >> i) & 1)
            count++;
    return count;
}

Hesaplama Sorusu · Uzay-Zaman Ödünleşimi

Soru 12: Renk Paletiyle Ödünleşim

800 × 600 bir görüntü (a) piksel başına 24 bit RGB, (b) piksel başına 8 bitlik palet indisi + 256 renklik palet (renk başına 3 bayt) ile saklanıyor. İki boyutu ve oranı hesaplayın. (b) neyi feda eder?

Cevabı göster

(a) 800 × 600 × 3 = 1.440.000 B.

(b) 800 × 600 × 1 + 256 × 3 = 480.000 + 768 = 480.768 B. Oran 1.440.000 / 480.768 ≈ 3 : 1.

Yer yaklaşık üçte bire iner; bedeli her piksel çizilirken bir tablo bakışı (zaman) ve en fazla 256 renk sınırıdır. GIF ve PNG-8 bu yöntemi kullanır.

Çoktan Seçmeli · İpuçları

Soru 13: Önbellek ile İpucu

Dağıtık bir dosya sisteminde istemci “bu dosya muhtemelen B sunucusunda” bilgisini tutuyor; kullanmadan önce B’ye soruyor, yanlışsa dizin hizmetine başvuruyor. Bu bilgi neden önbellek değil ipucudur?

C: önbellekteki değer her zaman doğru olmalıdır: kaynak değişince geçersiz kılınır (tutarlılık yükü). İpucu yanlış çıkabilir; doğruluğu kullanım anında ucuz bir denetimle sınanır. Diğer örnekler: dal tahmini, madvise ile verilen erişim ipucu.

Hesaplama Sorusu · Efsanevi Adam-Ay

Soru 14: Brooks Yasası

Gecikmiş bir projede 5 kişilik ekibe 3 kişi ekleniyor. (a) Her çift arasında bir iletişim yolu varsa yol sayısı kaçtan kaça çıkar, kaç kat artar? (b) Brooks’un önerdiği dağılıma (1/3 planlama, 1/6 kodlama, 1/4 modül testi, 1/4 sistem testi) göre 12 aylık bir projede her işe kaç ay düşer?

Cevabı göster

(a) n(n − 1) / 2: 5 kişide 10, 8 kişide 28 yol; 2,8 kat artış (kişi sayısı yalnız 1,6 kat). Yeni gelenleri eğitmek mevcut ekibin zamanını da tüketir: “Gecikmiş bir yazılım projesine eleman eklemek, onu daha da geciktirir.”

(b) Planlama 4, kodlama 2, modül testi 3, sistem testi 3 ay. Kod yazmak işin altıda biridir; zamanın yarısı teste gider.

Adım Adım Çalıştırma · git bisect

Soru 15: git bisect ile Regresyon Avı

v1 (commit #0) iyi, v2 (#600) kötü; aradaki commit’ler sırayla numaralı ve ilk kötü commit #222. git her adımda aralığın ortasını (⌊(iyi + kötü) / 2⌋) sınatıyor. Hangi commit’ler sınanır, kaç test gerekir?

0100200300400500600iyikötüaday: 600

İlk kötü commit 1…600 arasında. git her adımda aday aralığın ortasındaki commit’i çıkarır.

0100200300400500600iyikötü#300 kötüaday: 300

#300 sınanır: hata var, bad. İlk kötü commit #300 ya da öncesi. Aday 600 → 300.

0100200300400500600iyikötü#150 iyiaday: 150

#150 sınanır: hata yok, good. İlk kötü commit #150’den sonra. Aday 300 → 150.

0100200300400500600iyikötü#225 kötüaday: 75

#225 sınanır: hata var, bad. İlk kötü commit #225 ya da öncesi. Aday 150 → 75.

0100200300400500600iyikötü#187 iyiaday: 38

#187 sınanır: hata yok, good. İlk kötü commit #187’den sonra. Aday 75 → 38.

0100200300400500600iyikötü#222 kötüaday: 1

git bisect run kalanı betikle yürütür: #206 iyi, #215 iyi, #220 iyi, #222 kötü, #221 iyi. Toplam 9 test: “#222 is the first bad commit”.

0100200300400500600iyikötüaday: 1

reset ile başlangıç dalına dönülür. En kötü durumda ⌈log₂ 600⌉ = 10 test; 1 milyon commit için bile 20. Betik iyi için 0, kötü için 1–127 (125 hariç) döndürür.

git bisect start
git bisect bad  v2      # commit #600
git bisect good v1      # commit #0
# derle, başlat, sına:
git bisect bad          # ya da: good
git bisect run ./sina.sh
git bisect reset

Çoktan Seçmeli · Dinamik Denetleyiciler

Soru 16: Hangi Araç Neyi Yakalar?

Çekirdek hata ayıklama araçlarıyla yakaladıkları hata eşleştirilmiş. Hangisi yanlıştır?

C: kmemleak bellek sızıntısını bulur: hiçbir işaretçinin göstermediği ayrılmış blokları raporlar. Kilit sırasını lockdep, veri yarışını KCSAN denetler. KASAN gölge bellekle her erişimi sınar; bedeli birkaç kat yavaşlamadır, bu yüzden test çekirdeklerinde açılır.

Klasik Soru · Hata Ayıklama Stratejisi

Soru 17: Ara Sıra Görülen Use-After-Free

Bir sürücüde ara sıra görülen, printk eklenince kaybolan bir use-after-free hatası var. Hangi araçları hangi sırayla kullanırsınız? syzkaller neden KASAN açık bir çekirdekle çalıştırılır? Hata v6.11 ile v6.12 arasında (12.000 commit) girmişse ne yaparsınız?

Cevabı göster
  • KASAN (ve KCSAN) açık bir test çekirdeğini QEMU’da çalıştırın; hatayı syzkaller ya da stres testiyle tetikleyin.
  • KASAN raporu ilk geçersiz erişimde gelir ve nesnenin ayırma ve serbest bırakma yığın izlerini verir: nesnenin ömrü buradan çıkar. Gerekirse QEMU + gdb ile adım adım izlenir.
  • Fuzzer tek başına yalnız çökmeyi görür; sessiz bellek bozulmasını görünür kılan denetleyicidir.
  • printk zamanlamayı değiştirir (heisenbug): ftrace/eBPF gibi düşük yüklü izleyiciler tercih edilir.
  • git bisect: ⌈log₂ 12.000⌉ = 14 test (213 = 8.192 < 12.000 ≤ 16.384).

Çoktan Seçmeli · Rust, eBPF ve Unikernel

Soru 18: Unikernel Nereden Gelir?

MirageOS ve Unikraft gibi unikernel’ler, tek bir uygulamayı ona gereken işletim sistemi kütüphaneleriyle birlikte tek bir görüntü olarak derler. Bu fikir hangi sistem yapısının bulut sürümüdür?

A: exokernel’de soyutlamalar uygulamaya bağlanan kütüphane işletim sisteminde (libOS) bulunur; unikernel bu libOS’u uygulamayla birlikte tek adres alanında hipervizör üzerinde çalıştırır. Bedeli: hata ayıklama ve çok uygulamalı kullanım zordur.

Son

Bölüm 15: İşletim Sistemi Tasarımı: Çalışma Soruları
Konu anlatımı: İşletim sistemi tasarımı sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.