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

İşletim Sistemleri
Tasarım neden zor?İşletim sisteminin hedefleriArayüz ilkeleri ve paradigmalarSistem çağrısı arayüzüKatmanlı, exokernel, mikroçekirdekMekanizma, politika, diklikAdlandırma ve bağlama zamanıGerçekleştirme stratejileriYararlı tekniklerPerformans: takas, önbellek, ipucuProje yönetimi ve Brooks yasasıEğilimler: bulut, Rust, eBPF
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Zorluklar ve hedefler

İşletim sistemi tasarımını zorlaştıran etkenleri ve bir işletim sisteminin dört temel hedefini açıklamak.

Arayüz tasarımı

Basitlik, bütünlük ve verimlilik ilkelerini; yürütme ve veri paradigmalarını sistem çağrısı örnekleriyle tartışmak.

Sistem yapısı

Katmanlı, exokernel, mikroçekirdek tabanlı ve genişletilebilir yapıları ödünleşimleriyle karşılaştırmak.

Tasarım ilkeleri

Mekanizma/politika ayrımını, dikliği, iki düzeyli adlandırmayı, bağlama zamanını ve statik/dinamik yapıları uygulamak.

Teknikler ve performans

Dolaylılık, yeniden girişlilik, uzay-zaman takası, önbellek, ipucu ve yaygın durumu hızlandırma tekniklerini örneklerle kullanmak.

Proje ve eğilimler

Brooks yasasını ve ekip yapısını yorumlamak; sanallaştırma, çok çekirdek, Rust, eBPF ve unikernel eğilimlerini değerlendirmek.

Giriş

İşletim Sistemi Tasarlamak Neden Zor?

1 · Devasa boyut

Linux ≈ 40 milyon satır; kimse bütünü kavrayamaz.

2 · Eşzamanlılık

Aygıtlar, kesmeler, iş parçacıkları aynı anda: yarış, kilitlenme.

3 · Düşmanca kullanıcılar

Bazıları sistemi bozmak, veri çalmak ister; her girdi şüpheli.

4 · Yalıtıma rağmen paylaşım

Kullanıcılar ayrılmalı, ama seçtikleriyle bilgi paylaşabilmeli.

5 · Uzun ömür

20-30 yıl yaşar; gelecekteki donanım ve uygulamalar öngörülmeli.

6 · Genellik

Nasıl kullanılacağı bilinmez: telefondan süper bilgisayara.

7 · Taşınabilirlik

Farklı işlemci ve platformlar: x86-64, ARM64, RISC-V…

8 · Geriye dönük uyumluluk

Eski programlar çalışmalı; yeni fikirler eski kısıtlarla sınırlanır.

Tanenbaum’ın sekiz etkeni. Uzun bakım-onarım ihtiyacı 5. ve 8. maddelerin doğal sonucudur.

Giriş · Adım adım

İşletim Sisteminin Hedefleri

TarayıcıDerleyiciVeritabanıSoyutlamalarsüreçiş parçacığıadres uzayıdosyasoketİlkel işlemler (sistem çağrıları)fork · execve · mmap · open · read · write · send · recv · futexDonanım yönetimiCPUbellekSSD/diskağ kartıGPU

1. Soyutlamalar tanımlamak (abstractions): süreç, adres uzayı, dosya, soket gibi kavramlar donanımın karmaşıklığını gizler. Tasarımın en zor kısmı doğru soyutlamayı bulmaktır.

TarayıcıDerleyiciVeritabanıSoyutlamalarsüreçiş parçacığıadres uzayıdosyasoketİlkel işlemler (sistem çağrıları)fork · execve · mmap · open · read · write · send · recv · futexDonanım yönetimiCPUbellekSSD/diskağ kartıGPU

2. İlkel işlemler sağlamak (primitives): bu soyutlamalar üzerinde çalışan işlemler, yani sistem çağrıları. Örn. dosya için open/read/write/close.

TarayıcıDerleyiciVeritabanıher süreç kendi adres uzayında: biri çökerse diğerleri etkilenmezSoyutlamalarsüreçiş parçacığıadres uzayıdosyasoketİlkel işlemler (sistem çağrıları)fork · execve · mmap · open · read · write · send · recv · futexDonanım yönetimiCPUbellekSSD/diskağ kartıGPU

3. Yalıtım sağlamak (isolation): kullanıcılar ve süreçler birbirine karışamamalı; ama denetimli paylaşım (dosya izinleri, paylaşılan bellek) mümkün olmalı.

TarayıcıDerleyiciVeritabanıSoyutlamalarsüreçiş parçacığıadres uzayıdosyasoketİlkel işlemler (sistem çağrıları)fork · execve · mmap · open · read · write · send · recv · futexDonanım yönetimiCPUbellekSSD/diskağ kartıGPU

4. Donanımı yönetmek (hardware): kesmeler, zamanlayıcılar, MMU, aygıt denetleyicileri; düşük seviyeli işler çoğunlukla bu katmanda yapılır.

Arayüz Tasarımı

Arayüz Tasarımı İçin Yol Gösterici İlkeler

1 · Basitlik (simplicity)

“Mükemmelliğe, eklenecek bir şey kalmadığında değil, çıkarılacak bir şey kalmadığında ulaşılır.” (A. de Saint-Exupéry). Az sayıda, iyi düşünülmüş kavram öğrenmesi, gerçekleştirmesi ve doğrulaması kolaydır.

2 · Bütünlük (completeness)

“Her şey olabildiğince basit olmalı, ama daha basit değil.” (Einstein’a atfedilir). Arayüz, kullanıcıların ihtiyaç duyduğu her şeyi yapabilmelidir. Az mekanizma ile çok iş: MINIX 3 çekirdeği iletişim için yalnızca birkaç ilkel (send, receive, sendrec, notify) sunar.

3 · Verimlilik (efficiency)

Bir özellik ya da sistem çağrısı verimli gerçekleştirilemiyorsa muhtemelen sahip olmaya değmez. Programcı bir çağrının yaklaşık maliyetini sezebilmelidir: lseek ucuz, read pahalı olabilir.

Pratik kural: her sistem çağrısı tek bir işi iyi yapmalı. Özellik eklemek kolay, kaldırmak neredeyse imkânsızdır (geriye dönük uyumluluk).

Arayüz Tasarımı

“Küçük Güzeldir”

1101001000seL4 mikroçekirdeği≈ 12UNIX V7 (1979)≈ 50Linux x86-64 (6.x)≈ 460Windows NT + win32k≈ 1700sistem çağrısı sayısı (logaritmik ölçek, yaklaşık)Ne kadar az çağrı, o kadar küçük saldırı yüzeyi ve doğrulama yükü
  • Küçük güzeldir: az sayıda genel çağrı, çok sayıda özel çağrıdan iyidir.
  • seL4’ün çekirdeği yaklaşık 10 bin satırdır ve biçimsel olarak doğrulanmıştır; milyonlarca satırlık bir çekirdekte bu mümkün değil.
  • Linux’ta çağrı sayısı her yıl birkaç tane artar (ör. io_uring_*, landlock_*, mseal).
  • Windows’ta belgelenmiş arayüz Win32 API’dir; çekirdek çağrıları sürümden sürüme değişir.

Arayüz Tasarımı

Kullanıcı Arayüzü Paradigmaları

Komut satırı (CLI)

Kabuk, metin komutları, borular. Otomasyon ve uzaktan yönetim için hâlâ vazgeçilmez.

WIMP / GUI

Pencere, simge, menü, işaretçi (Windows, Icons, Menus, Pointer). Fare tuşlarının anlamı her uygulamada aynı olmalı.

Dokunmatik ve mobil

Hareketler (kaydır, yakınlaştır), tam ekran uygulamalar, bildirim merkezi.

Ses, sohbet ve ajanlar

Sesli asistanlar ve doğal dil arayüzleri; işletim sistemi hizmetlerine yeni bir giriş noktası.

Kullanıcı arayüzü çoğu zaman çekirdeğin parçası değildir, ama paradigma tüm sistem tasarımını etkiler: GUI olay güdümlü bir yürütme modeli, hızlı pencere sistemi ve tutarlı bir uygulama çerçevesi gerektirir. Önemli olan tutarlılıktır: aynı eylem her yerde aynı sonucu vermelidir.

Arayüz Tasarımı

Yürütme Paradigmaları

(a) Algoritmik kod

int main(void)
{
    int x, y;
    init();
    do_something();
    read(fd, &x, sizeof x);
    do_something_else();
    write(fd, &y, sizeof y);
    keep_going();
    exit(0);
}

Program akışı program belirler; işletim sistemine hizmet için çağrı yapar. Derleyici, sıralayıcı, toplu işler.

(b) Olay güdümlü kod (event-driven)

int main(void)
{
    msg_t msg;
    init();
    while (get_message(&msg)) {
        switch (msg.type) {
        case 1: ... ; break;
        case 2: ... ; break;
        case 3: ... ; break;
        }
    }
}

Akışı dış olaylar (tuş, tıklama, paket, zamanlayıcı) belirler. GUI’ler, sunucular, mikroçekirdek sunucuları.

Yürütme paradigmasının seçimi, sistem çağrılarını da biçimlendirir: algoritmik model engelleyen (blocking) read ister; olay güdümlü model ise “sıradaki olayı ver” türünden bir çağrı (get_message, epoll_wait, io_uring_enter) ister.

Arayüz Tasarımı · Kodu adım adım çalıştır

Olay Döngüsü Nasıl Çalışır?

int main(void) {
    msg_t m;
    init();
    while (get_message(&m)) {
        switch (m.type) {
        case KEY:   on_key(&m);   break;
        case CLICK: on_click(&m); break;
        case TIMER: on_timer(&m); break;
        }
    }
    return 0;
}
olay kuyruğu(boş)get_messagehenüz yokon_keyon_clickon_timer

Program başlar, init() pencereyi ve kaynakları hazırlar. Kuyruk boş.

olay kuyruğuCLICKKEYTIMER↑ sıranın başıget_messageolay bekliyoron_keyon_clickon_timer

Kullanıcı tıklar, bir tuşa basar, zamanlayıcı dolar. Olayları işletim sistemi/pencere sistemi toplar ve uygulamanın kuyruğuna ekler.

olay kuyruğuKEYTIMER↑ sıranın başıget_messageCLICK döndüon_keyon_clickon_timerm.type = CLICK

get_message sıranın başındaki CLICK’i döndürür; switch onu on_click’e yönlendirir.

olay kuyruğuTIMER↑ sıranın başıget_messageKEY döndüon_keyon_clickon_timerm.type = KEY

İşleyici kısa sürede biter ve döngü başa döner. Sıradaki olay KEY: on_key çalışır.

olay kuyruğu(boş)get_messageTIMER döndüon_keyon_clickon_timerm.type = TIMER

TIMER olayı on_timer’a gider (ör. imleci yakıp söndürmek). Uzun süren bir işleyici tüm arayüzü dondurur; uzun işler ayrı iş parçacığına verilir.

olay kuyruğu(boş)get_messageengellendion_keyon_clickon_timer

Kuyruk boş: get_message engellenir, süreç uyur ve CPU harcamaz. Yeni bir olay onu uyandırır.

olay kuyruğuQUIT↑ sıranın başıget_messageolay bekliyoron_keyon_clickon_timer

Kullanıcı pencereyi kapatır: kuyruğa QUIT olayı gelir.

olay kuyruğu(boş)get_message0 döndürdüon_keyon_clickon_timerm.type = QUIT

QUIT için get_message 0 döndürür, döngü biter, program sonlanır. Aynı kalıp nginx/Node.js (epoll) ve mikroçekirdek sunucularında da kullanılır.

Arayüz Tasarımı

Veri Paradigmaları

open · read · write · closetek arayüz, tek tanımlayıcı türü (fd)normal dosya/home/ali/not.txtaygıt/dev/nvme0n1borupipe(fd)çekirdek bilgisi/proc/cpuinfosoketsocket()UNIX: “her şey bir dosyadır” · Plan 9: ağ ve pencereler de dosya sistemiWindows: “her şey bir nesnedir” → HANDLEnesne yöneticisi: \Device\HarddiskVolume1, olay, mutex, süreç, iş parçacığı
  • Ortak bir veri paradigması, aynı aracın (cat, dd, yönlendirme) her kaynakta çalışmasını sağlar: cat /proc/loadavg.
  • Bedeli: bazı aygıtlar dosya modeline sığmaz; o zaman her şey ioctl gibi “kaçış kapılarına” yığılır.

Arayüz Tasarımı

Sistem Çağrısı Arayüzü

kütüphane (glibc, kullanıcı alanı)execlexeclpexecleexecvexecvpexecvpekullanıcı / çekirdek sınırıexecvetek bir sistem çağrısı: yol, argv[], envp[]
  • Ayrımı koru: çağrı az ve genel, kolaylık fonksiyonları kütüphanede. Yeni bir kolaylık eklemek çekirdeği değiştirmez.
  • Bağımsız bileşenler: UNIX süreç oluşturmayı ikiye böler: fork + execve. Arada yönlendirme, chdir vb. yapılabilir.
  • Windows’ta CreateProcess tek çağrıda 10 parametre alır: güçlü ama karmaşık.
  • Modern eğilim: posix_spawn (fork maliyetini önler) ve toplu çağrı arayüzleri (io_uring: tek geçişte çok sayıda istek).

Sistem Yapısı

Sistem Yapısı Seçenekleri

YapıÇekirdekte ne var?ArtısıEksisiÖrnek
MonolitikHer şey tek adres uzayındaHızlı, doğrudan çağrıBir hata tüm sistemi düşürürLinux, FreeBSD
KatmanlıHiyerarşik katmanlarModüler, katman katman testKatman sırası ve geçiş maliyetiTHE (1968), MULTICS
ExokernelYalnızca güvenli kaynak paylaştırmaUygulamaya özel soyutlamaKütüphane OS karmaşıklığıAegis/ExOS (MIT)
MikroçekirdekIPC, zamanlama, bellek eşlemeGüvenilirlik, yalıtımMesaj (IPC) maliyetiMINIX 3, QNX, seL4, Zircon
GenişletilebilirÇekirdek + güvenli eklentilerÇalışırken uyarlanırEklentinin güvenliğiSPIN, Linux eBPF
HibritMikroçekirdek fikri, monolitik uygulamaPragmatik dengeSaf modelin yararları kısmen kaybolurWindows NT, macOS XNU
Bu bölümdeki beş yapı (katmanlı, exokernel, mikroçekirdek tabanlı istemci-sunucu, genişletilebilir sistemler ve çekirdek iş parçacıkları) birbirini dışlamaz: gerçek sistemler birkaçını birlikte kullanır. Örneğin Linux monolitiktir ama modüller ve eBPF ile genişletilebilir, çekirdek iş parçacıkları kullanır.

Sistem Yapısı · Adım adım

Katmanlı Sistemler: Yedi Katmanlı Bir Tasarım

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizleme

Tanenbaum’ın önerdiği yedi katmanlı tasarım. 1. katman donanım farklılıklarını gizler; üst katmanlar hep alttakinin sunduğu soyutlamayla çalışır.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemeread(fd, buf, n)

Uygulama read çağırır; tuzak 7. katmana gelir. Parametreler (fd geçerli mi, tampon kullanıcı alanında mı?) burada denetlenir.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemeblok 4711 gerekli

Dosya sistemi (ext4) dosya ofsetini disk bloğuna çevirir. Blok önbellekte yoksa alt katmanlardan istenir.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemesayfa çerçevesi ayır

Sanal bellek, verinin konacağı sayfa önbelleği çerçevesini ayırır ve kullanıcı tamponunun eşlemesini doğrular.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemeNVMe komutu

NVMe sürücüsü okuma komutunu aygıtın kuyruğuna yazar.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemeiş parçacığı uyur

Çağıran iş parçacığı G/Ç bitene kadar engellenir; zamanlayıcı başka bir iş parçacığını çalıştırır.

7Sistem çağrısı işleyicisi6Dosya sistemiext4BtrfsNFS5Sanal bellek4Aygıt sürücüleriNVMeağUSBGPU3İş parçacıkları, zamanlama, senkronizasyon2Kesme işleme, bağlam anahtarlama, MMU1Düşük seviyeli donanımı gizlemekesme geldi

Aygıt bitince kesme üretir; 2. katman kesmeyi işler, uyuyan iş parçacığını hazır yapar. Sonuç katmanlar boyunca yukarı döner.

Her katman yalnızca altındakini kullanır; arayüzler iyi tanımlıysa bir katmandaki değişiklik diğerlerini etkilemez ve katmanlar alttan üste tek tek test edilir. Bedeli: katman sırasını seçmek ve geçiş maliyeti. Kaba görünüm: uygulama → kütüphane → sistem çağrısı → çekirdek → donanım.

Sistem Yapısı

Exokernel

Web sunucusukütüphane OSözel libOS: sıfır kopya ağVeritabanıkütüphane OSözel libOS: kendi tampon yönetimiKabuk, derleyicikütüphane OSUNIX benzeri libOSkullanıcı moduçekirdek moduExokernelkim hangi disk bloğuna, sayfaya, CPU dilimine sahip? Yalnızca bunu kaydeder ve denetlerDonanım: CPU · fiziksel bellek · disk · ağ
  • Donanım ile yazılım arasında en ince soyutlama katmanı.
  • Kaynaklar ayrıntılı (blok, sayfa, zaman dilimi) düzeyinde ayrılır; soyutlamalar (dosya, süreç) kullanıcı alanındaki kütüphane OS’ta.
  • Sanal makineden farkı: her VM’e makinenin kopyası değil, kaynağın bir bölümü verilir; yeniden eşleme katmanı gerekmez.
  • Bedeli: tasarım ve uygulama karmaşıklığı, uygulamalar arası paylaşımın zorluğu. Fikri bugün unikernel’lerde yaşıyor.

Düzeltme: eski sunumdaki “çekirdek bileşenlerinin dinamik yüklenmesi” exokernel’e değil, genişletilebilir sistemlere ait bir özelliktir.

Sistem Yapısı · Adım adım

Mikroçekirdek Tabanlı İstemci-Sunucu Sistemleri

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletme

Çekirdek olabildiğince küçük: yalnızca süreç yönetimi, süreçler arası iletişim (IPC) ve temel bellek eşleme. Dosya sistemi, sürücüler, hatta bellek politikası kullanıcı süreçleridir.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmesend(FS, istek)

İstemci bir dosya okumak ister: dosya sunucusuna mesaj gönderir. Bu, çekirdeğe yapılan tek tür çağrıdır.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmemesaj kopyalandı

Mikroçekirdek mesajı dosya sunucusunun adres uzayına kopyalar (veya eşler) ve onu çalıştırır.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmeblok oku

Dosya sunucusu bloğu disk sürücüsünden ister; o da bir kullanıcı sürecidir. Aygıt yazmaçlarına erişim çekirdeğin verdiği izinlerle olur.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmeyanıt: veri

Yanıt aynı yoldan istemciye döner. Her istek birden çok bağlam anahtarlama ve kopyalama demektir: performans bedeli.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmeçöktü!

Kazanç: sürücü çökerse yalnız o süreç ölür, çekirdek ve diğer sunucular çalışmaya devam eder.

İstemciDosya sunucusuBellek sunucusuDisk sürücüsüYeniden doğuşkullanıcı süreçlerikullanıcı moduçekirdek moduMikroçekirdekIPC (mesaj) · zamanlama · adres uzayı · kesmeleri iletmeyeniden başlat

MINIX 3’te yeniden doğuş sunucusu (reincarnation server) çöken sürücüyü fark edip yeniden başlatır: kendini onaran sistem.

Örnekler: Mach (macOS’taki XNU melez bir türevidir), QNX (otomotiv), L4 ailesi ve biçimsel doğrulanmış seL4, MINIX 3, Google Fuchsia’nın Zircon çekirdeği. Sunucular ağdaki farklı düğümlerde de çalışabilir; ancak “mesajlaşma kendiliğinden güvenlidir” demek abartıdır: güvenlik, çekirdeğin yetki denetimine bağlıdır.

Sistem Yapısı

Genişletilebilir Sistemler

kullanıcı alanıC kaynağıprog.bpf.cclangBPF bayt kodubpf()sistem çağrısıçekirdekDoğrulayıcısınırlı döngü, bellek güvenliJITyerel kodyükleme reddedilirkprobe/izlemeXDP (ağ)güvenlik (LSM)sched_extYüklenebilir modül (insmod): denetimsiz
  • Çekirdek temel işlevleri sağlar; değişen ihtiyaçlar için çalışırken yeni bileşen eklenir.
  • Üçüncü taraflar sisteme özellik ekleyebilir; uyumluluk ve güvenlik en büyük sorundur.
  • Klasik modül tam yetkilidir: bir hata çekirdeği çökertir. SPIN (1995) eklentileri güvenli dil (Modula-3) ile sınırladı.
  • Bugün Linux’ta eBPF: doğrulanmış küçük programlar; izleme, ağ, güvenlik ve 6.12’den beri zamanlayıcı (sched_ext).

Sistem Yapısı

Çekirdek İş Parçacıkları

kullanıcı süreçleri (kendi adres uzayları)bashfirefoxpostgresçekirdek adres uzayı (tüm süreçlerde ortak)kthreaddkworker/0:1ksoftirqd/0kswapd0jbd2/nvme0n1
  • Çekirdek tarafından oluşturulur ve yönetilir (kthread_create); kullanıcı adres uzayları yoktur, yalnızca çekirdek belleğinde çalışırlar.
  • Normal iş parçacığı gibi zamanlanır, engellenebilir, uyuyabilir: kesme işleyicisinde yapılamayan uzun işler buraya ertelenir.
  • Bağlam anahtarlama ucuz: adres uzayı (sayfa tablosu) değişmez.
  • Örnekler: ertelenmiş iş (kworker), yumuşak kesmeler (ksoftirqd), sayfa geri kazanma (kswapd), günlük yazma (jbd2).
  • ps -ef çıktısında köşeli parantez içinde görünürler: [kswapd0].

Düzeltme: kullanıcı süreçleri çekirdek iş parçacığı oluşturamaz; sistem çağrıları yalnızca çekirdeğin zaten çalıştırdığı iş parçacıklarına iş verebilir (ör. io_uring’in iş havuzu).

Tasarım İlkeleri · Adım adım

Mekanizma ve Politikanın Ayrılması

Politika (kullanıcı alanı)henüz müdahale yokçekirdekMekanizma: öncelik tabanlı zamanlayıcı (en yüksek öncelikli hazır iş parçacığını seç)T1 arayüzöncelik 5T2 sorguöncelik 3T3 yedeklemeöncelik 8T4 günlüköncelik 1CPU → T3 yedekleme

Çekirdek yalnızca bir mekanizma sunar: “en yüksek öncelikli hazır iş parçacığını çalıştır”. Şu an T3 (yedekleme, öncelik 8) seçiliyor.

Politika (kullanıcı alanı)sched_setattr(T2, prio=9); sched_setattr(T3, prio=2);çekirdekMekanizma: öncelik tabanlı zamanlayıcı (en yüksek öncelikli hazır iş parçacığını seç)T1 arayüzöncelik 5T2 sorguöncelik 3T3 yedeklemeöncelik 8T4 günlüköncelik 1CPU → T3 yedekleme

Veritabanı süreci kendi iş parçacıklarını en iyi bilen taraftır: sorguların önemli, yedeklemenin bekleyebileceğine karar verir. Bu bir politikadır ve bir sistem çağrısıyla aktarılır.

Politika (kullanıcı alanı)sched_setattr(T2, prio=9); sched_setattr(T3, prio=2);çekirdekMekanizma: öncelik tabanlı zamanlayıcı (en yüksek öncelikli hazır iş parçacığını seç)T1 arayüzöncelik 5T2 sorguöncelik 9T3 yedeklemeöncelik 2T4 günlüköncelik 1CPU → T2 sorgu

Çekirdek kodu hiç değişmeden artık T2’yi seçer. Aynı mekanizma, farklı politikayla farklı davranış üretir.

Politika (kullanıcı alanı)etkileşimli politika: arayüz iş parçacığı önceçekirdekMekanizma: öncelik tabanlı zamanlayıcı (en yüksek öncelikli hazır iş parçacığını seç)T1 arayüzöncelik 9T2 sorguöncelik 6T3 yedeklemeöncelik 2T4 günlüköncelik 1CPU → T1 arayüz

Başka bir uygulama başka bir politika uygular. Linux 6.12’deki sched_ext bunu bir adım öteye taşır: zamanlama politikasının tamamı bir eBPF programı olarak yüklenebilir.

Diğer örnekler: sayfalama (mekanizma: MMU, çerçeve tahsisi; politika: hangi sayfa çıkarılsın), CPU frekansı (mekanizma: cpufreq sürücüsü; politika: schedutil/powersave yönetici), güvenlik (mekanizma: LSM kancaları; politika: SELinux kuralları).

Tasarım İlkeleri

Diklik (Orthogonality)

fork()ara biçimpthread_create()CLONE_VMadres uzayıkopyalakopyalapaylaşCLONE_FSkök/çalışma dizinikopyalapaylaşpaylaşCLONE_FILESaçık dosyalarkopyalapaylaşpaylaşCLONE_SIGHANDsinyal işleyicilerkopyalakopyalapaylaşCLONE_THREADaynı iş parçacığı grubukopyalakopyalapaylaşsüreç ← tek çağrı: clone(flags) → iş parçacığı
  • Diklik (orthogonality): ayrı kavramları bağımsız olarak birleştirebilme. Birini değiştirmek diğerini etkilemez.
  • Linux clone: neyin paylaşılacağı ayrı ayrı bayraklarla seçilir. Süreç ve iş parçacığı aynı mekanizmanın iki ucudur; konteynerler de CLONE_NEW* bayraklarıyla kurulur.
  • Windows: süreç bir kaynak kabıdır, iş parçacığı ise zamanlama birimi; iki kavram ayrıdır.
  • C dilinde de örnek: static (ömür) ile tür bağımsız seçilir.

Tasarım İlkeleri

Adlandırma: İki Düzeyli Adlar

harici ad (insan için)/usr/ast/mboxdizin (eşleme tablosu)grants64books92mbox60minix81dahili ad (sistem için)i-node 60sahip, izinler, boyutblok listesi →
Harici adEşleyenDahili ad
/usr/ast/mboxdizini-node numarası
www.giresun.edu.trDNSIP adresi → (ARP) MAC adresi
dosya tanımlayıcı 3süreç dosya tablosuçekirdekteki struct file
sanal adressayfa tablosufiziksel çerçeve
\Device\Harddisk0nesne yöneticisiçekirdek nesnesi (HANDLE)

Ad, insanların hatırlayabileceği biçimde (ASCII/Unicode dizgisi) seçilir; sistem içinde ise hızlı ve benzersiz bir sayı kullanılır. Aradaki eşleme, adı değiştirmeden nesneyi taşımaya olanak verir.

Tasarım İlkeleri · Adım adım

Ad Çözümleme Adım Adım

/usr/ast/mboxdisk okuması: 0i-node 1 → kök dizin · blok 1i-node 6 → /usr · blok 132i-node 26 → /usr/ast · blok 406

Çekirdek open("/usr/ast/mbox") çağrısını alır. Yol bileşenlere ayrılır; hiçbir şey önbellekte yoksa her bileşen için diskten okunmak gerekir.

/usr/ast/mboxdisk okuması: 2i-node 1 → kök dizin · blok 1.1..1bin4dev7lib14etc9usr6tmp8i-node 6 → /usr · blok 132i-node 26 → /usr/ast · blok 406

Kök dizinin i-node’u (i-node 1) okunur, ardından kök dizinin verisi (blok 1). Doğrusal arama: usr → i-node 6. 2 okuma.

/usr/ast/mboxdisk okuması: 4i-node 1 → kök dizin · blok 1.1..1bin4dev7lib14etc9usr6tmp8i-node 6 → /usr · blok 132.6..1dick19erik30jim51ast26bal45i-node 26 → /usr/ast · blok 406

/usr için i-node 6 okunur, sonra /usr dizini (blok 132). ast → i-node 26. 4 okuma.

/usr/ast/mboxdisk okuması: 6i-node 1 → kök dizin · blok 1.1..1bin4dev7lib14etc9usr6tmp8i-node 6 → /usr · blok 132.6..1dick19erik30jim51ast26bal45i-node 26 → /usr/ast · blok 406.26..6grants64books92mbox60minix81src17

/usr/ast için i-node 26 okunur, sonra dizin bloğu 406. mbox → i-node 60. 6 okuma.

/usr/ast/mboxdisk okuması: 7i-node 1 → kök dizin · blok 1.1..1bin4dev7lib14etc9usr6tmp8i-node 6 → /usr · blok 132.6..1dick19erik30jim51ast26bal45i-node 26 → /usr/ast · blok 406.26..6grants64books92mbox60minix81src17mbox → i-node 60 (7. okuma)

Son olarak dosyanın kendi i-node’u (60) okunur. Sadece dosyayı bulmak için 7 disk erişimi gerekti: bu yüzden önbellek şart (bkz. Performans bölümü).

Tasarım İlkeleri

Bağlama Zamanı

yazılırkenmutlak adreskoda gömülüderlemesabit yüklemeadresibağlamastatikkütüphaneyüklemeyer değiştirme,ASLRçalışmasanal bellek,dlopen, DNS← erken bağlama: basit, hızlı, az esnekgeç bağlama: karmaşık, esnek →
Erken bağlama (early binding)

Ad ile nesne arasındaki ilişki önceden sabitlenir. Basit ve hızlı, ama az esnek: program yalnızca belirli adreste çalışır, kütüphane güncellenince yeniden derlenir.

Geç bağlama (late binding)

İlişki mümkün olan en son anda kurulur. Daha karmaşık (ek dolaylılık, çalışma zamanı maliyeti) ama daha esnek: sayfa nereye yüklenirse yüklensin, kütüphane güncellenince program değişmez.

Bağlama zamanı, “bir ad hangi anda gerçek nesneye bağlanır?” sorusudur. İşletim sistemleri genel olarak geç bağlamayı seçer; örneğin sanal bellek, bir sayfanın fiziksel yerini her erişimde (TLB yardımıyla) yeniden çözer.

Tasarım İlkeleri · Kodu adım adım çalıştır

Statik ve Dinamik Yapılar

found = 0;
for (p = &proc_table[0];
     p < &proc_table[PROC_TABLE_SIZE];
     p++) {
    if (p->proc_pid == pid) {
        found = 1;
        break;
    }
}
proc_table[PROC_TABLE_SIZE = 6]1[0]314[1]boş[2]42[3]977[4]boş[5]aranan pid = 42

Statik süreç tablosu: altı giriş, bazıları boş (pid 0). Aranan pid 42. found sıfırlanır.

proc_table[PROC_TABLE_SIZE = 6]1[0]314[1]boş[2]42[3]977[4]boş[5]paranan pid = 42

İşaretçi tablonun başına konur. proc_table[0]’ın pid’i 1: eşleşmez.

proc_table[PROC_TABLE_SIZE = 6]1[0]314[1]boş[2]42[3]977[4]boş[5]paranan pid = 42

p++ bir sonraki yapıya ilerler (bayta değil). 314 ≠ 42.

proc_table[PROC_TABLE_SIZE = 6]1[0]314[1]boş[2]42[3]977[4]boş[5]paranan pid = 42

Boş giriş (pid 0) da tek tek taranır: doğrusal aramanın bedeli.

proc_table[PROC_TABLE_SIZE = 6]1[0]314[1]boş[2]42[3]977[4]boş[5]paranan pid = 42

Eşleşme: found = 1, break ile döngüden çıkılır. En kötü durumda tüm tablo taranır: O(n). Küçük ve sabit bir tablo için bu basit kod yeterlidir.

Statik tablo: basit, ayırıcı gerektirmez, ama dolunca yeni süreç oluşturulamaz (eski UNIX’te NPROC). Dinamik yapı (bağlı liste, karma tablosu, Linux’ta xarray): esnek ve aramada O(1)’e yakın, ama bellek ayırıcı, parçalanma ve karmaşık kilitleme getirir. Ara yol: boyutu ayarlanabilir tablolar (/proc/sys/kernel/pid_max).

Tasarım İlkeleri

Yukarıdan Aşağı ve Aşağıdan Yukarı Gerçekleştirme

Sistem çağrısı işleyicisiDosya sistemiSanal bellekSürücülerİş parçacıklarıDonanım soyutlama (HAL)yukarıdanaşağıalt katmanlarkoçan (stub)aşağıdanyukarıher katmanhemen test edilir
Yukarıdan aşağı

Önce sistem çağrısı işleyicileri yazılır, alt katmanlar koçan (stub) olarak bırakılır. Arayüz erken netleşir; ama tüm sistem bitmeden gerçekçi test zordur.

Aşağıdan yukarı

Önce donanımı gizleyen katman, kesmeler, zamanlayıcı, sonra iş parçacıkları… Her katman bittiğinde test edilir. Tanenbaum gerçekleştirmede bu yolu önerir; tasarım ise yukarıdan aşağı düşünülmelidir.

Tasarım İlkeleri

Senkron ve Asenkron İletişim

Senkron (engelleyen)gönderenalıcı / aygıtAsenkron (engellemeyen)gönderenalıcı / aygıtsend(istek)engellendiyanıtdevam edersubmit(istek)başka işler yapartamamlanma: sinyal / geri çağırma / CQ
  • Senkron: programlaması kolay, akış sıralı okunur; ama her istek için bir iş parçacığı bekler.
  • Mikroçekirdeklerde IPC genelde senkrondur (L4, seL4): tampon gerekmez, çok hızlıdır.
  • Asenkron: tek iş parçacığı binlerce isteği yürütebilir; ama yarış, hata yönetimi ve tamponlama zorlaşır.
  • Linux io_uring: gönderim (SQ) ve tamamlanma (CQ) halkaları, sistem çağrısı olmadan bile istek gönderilebilir.

Yararlı Teknikler

Donanımı Gizleme

CPU türüne bağlı koşullu derleme

#include "config.h"
void init(void)
{
#if (CPU == X86_64)
    /* x86-64 başlatma kodu */
#endif
#if (CPU == ARM64)
    /* ARM64 başlatma kodu */
#endif
#if (CPU == RISCV64)
    /* RISC-V başlatma kodu */
#endif
}

Sözcük uzunluğuna bağlı derleme

#include "config.h"
#if (WORD_LENGTH == 32)
typedef int Register;
#endif
#if (WORD_LENGTH == 64)
typedef long Register;
#endif
Register R0, R1, R2, R3;

/* bugün: <stdint.h> */
typedef uintptr_t Register;
Donanıma bağımlı kodu az sayıda dosyada toplamak taşınabilirliğin anahtarıdır: Windows’ta HAL (Hardware Abstraction Layer), Linux’ta arch/x86, arch/arm64, arch/riscv dizinleri. Yeni bir işlemciye taşırken yalnız bu kısım yeniden yazılır. Koşullu derleme ölçülü kullanılmalı: her yere dağılan #ifdef kodu okunmaz hâle getirir.

Kodlar Tanenbaum’daki Pentium/UltraSPARC örneğinin güncellenmiş hâlidir.

Yararlı Teknikler · Adım adım

Dolaylılık (Indirection)

fiziksel tuşU’nun sağındakitarama kodu0x17 (set 1)tuş eşlem tablosu (keymap)US (QWERTY)iTürkçe QıTürkçe Fn

Kullanıcı U’nun sağındaki tuşa basar. Klavye karakter değil, tuşun konumunu bildirir.

fiziksel tuşU’nun sağındakitarama kodu0x17 (set 1)tuş eşlem tablosu (keymap)US (QWERTY)iTürkçe QıTürkçe Fniuygulamaya giden karakter

Klavye 0x17 tarama kodunu gönderir (USB klavyelerde HID kullanım kodu; sürücü ortak bir koda çevirir). ABD eşlemesiyle bu i olur.

fiziksel tuşU’nun sağındakitarama kodu0x17 (set 1)tuş eşlem tablosu (keymap)US (QWERTY)iTürkçe QıTürkçe Fnıuygulamaya giden karakter

Yalnızca tablo Türkçe Q ile değiştirilir: aynı tuş artık ı üretir. Donanım ve uygulama değişmedi.

fiziksel tuşU’nun sağındakitarama kodu0x17 (set 1)tuş eşlem tablosu (keymap)US (QWERTY)iTürkçe QıTürkçe Fnnuygulamaya giden karakter

Türkçe F eşlemesinde aynı tuş n olur. Ek bir adım (dolaylılık) esneklik sağlar; bedeli bir tablo okuması.

“Bilgisayar bilimindeki her sorun, bir dolaylılık düzeyi daha ile çözülebilir.” (David Wheeler). İşletim sistemlerinde: sanal bellek (sayfa tablosu), dosya tanımlayıcıları, sembolik bağlar, i-node, aygıt sınıfları.

Yararlı Teknikler

Yeniden Kullanım ve Yeniden Girişlilik

Yeniden kullanılabilirlik

Aynı kodu farklı yerlerde kullanmak: tek bir bit eşlem (bitmap) modülü boş disk bloklarını, bellek çerçevelerini ve PID’leri izleyebilir. Linux’ta ortak list.h, kırmızı-siyah ağaç, xarray.

Yeniden girişlilik (reentrancy)

Bir kod parçası aynı anda iki kez çalışabilmelidir: biri yürütülürken kesme gelip aynı fonksiyonu çağırabilir ya da başka bir çekirdek aynı kodu çalıştırır. Kural: paylaşılan statik değişken yok, gerekiyorsa kilit.

char *strtok(char *s, const char *d)
{
    static char *last; /* paylaşılan durum! */
    ...
}

/* yeniden girişli sürüm: durum çağıranda */
char *strtok_r(char *s, const char *d,
               char **saveptr);

strtok içindeki static değişken, iki iş parçacığı ya da bir kesme işleyicisi aynı anda kullanınca bozulur.

Yararlı Teknikler

Kaba Kuvvet ve Önce Hata Denetimi

Kaba kuvvet (brute force)

  • Basit ama “yavaş” görünen çözüm çoğu zaman yeterlidir: 50 girişlik bir tabloda doğrusal arama, karma tablosundan hızlı ve hatasız olabilir.
  • Karmaşık algoritma ancak ölçüm gerekli gösterirse: n büyükse veya kod sıcak yoldaysa.
  • Sıralama: küçük dizilerde ekleme sıralaması, büyüklerde birleştirme/yığın sıralaması.

Önce hataları denetle

Kötü: kaynak alındıktan sonra denetim

lock(&tbl_lock);
buf = kmalloc(n, GFP_KERNEL);
if (n > MAX || !access_ok(u, n)) {
    kfree(buf);
    unlock(&tbl_lock);
    return -EINVAL;
}

İyi: önce denetim, sonra kaynak

if (n > MAX || !access_ok(u, n))
    return -EINVAL; /* önce denetle */
buf = kmalloc(n, GFP_KERNEL);
if (!buf)
    return -ENOMEM;
lock(&tbl_lock);
...

Parametreleri kilit ve bellek almadan önce doğrulamak, hata yolundaki geri alma kodunu (ve unutulan unlock hatalarını) ortadan kaldırır.

Performans

Performans: Neden Yavaş, Neyi Hızlandırmalı?

Neden yavaş?

Özellik şişkinliği: her sürüm yeni özellik ekler, eskisini çıkaramaz. Geriye uyumluluk katmanları, güvenlik önlemleri (ör. Spectre/Meltdown yamaları sistem çağrısı maliyetini artırdı), genellik uğruna eklenen dolaylılık.

Neler optimize edilmeli?

Yalnızca ölçümle darboğaz olduğu gösterilen kısımlar. “İyi yeterlidir”: %5’lik kazanç için kodu iki kat karmaşıklaştırmak çoğu zaman değmez.

Önce doğru, sonra hızlı

“Erken optimizasyon tüm kötülüklerin anasıdır.” (D. Knuth). Ölçme araçları: perf, eBPF tabanlı bpftrace, alev grafikleri.

Klasik teknikler

Uzay-zaman takası · önbellekleme · ipuçları · yerelliği kullanmak · yaygın durumu hızlandırmak. Sonraki slaytlarda her biri örnekleniyor.

Donanım on yıllarda binlerce kat hızlandı, ama hissedilen hız aynı oranda artmadı: artışın önemli kısmını yazılımın büyümesi tüketti.

Performans · Kodu adım adım çalıştır

Uzay-Zaman Takası: (a) Döngüyle Bit Sayma

#define BYTE_SIZE 8
int bit_count(int byte)
{
    int i, count = 0;
    for (i = 0; i < BYTE_SIZE; i++)
        if ((byte >> i) & 1)
            count++;
    return count;
}
byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7count = 0

Örnek bayt 0xB7 (183). Döngüyle her bit tek tek sınanacak; sayaç sıfırdan başlar.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 0count = 1

(byte >> 0) & 1 = 1: sayaç artar.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 1count = 2

Kaydır, maskele, karşılaştır: her bit için birkaç komut ve bir dal.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 2count = 3

Bit 2 de 1.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 3count = 3

Bit 3 sıfır: dal alınmaz, sayaç değişmez.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 5count = 5

Bit 4 ve 5 de 1.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 6count = 5

Bit 6 sıfır.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7i = 7count = 6

Son bit 1. Döngü 8 kez döndü.

byte = 0xB7 = 1011 01111b01b11b20b31b41b50b61b7count = 6

Sonuç 6. Bellek yok denecek kadar az, ama bayt başına yaklaşık 8 tur × birkaç komut. Daha hızlı olabilir mi? Bir sonraki slayt: yer harcayıp zaman kazanmak.

Performans

Uzay-Zaman Takası: (b) Makro ve (c) Tablo

/* (b) makro: döngü yok */
#define bit_count(b) ((b&1) + ((b>>1)&1) + \
    ((b>>2)&1) + ... + ((b>>7)&1))

/* (c) tablo: 256 bayt */
char bits[256] =
    {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, ...};
#define bit_count(b) (int) bits[b]
YöntemBellekBayt başına iş
(a) döngü~08 tur: kaydır, maskele, dallan
(b) makro~0~24 komut, dal yok
(c) 256’lık tablo256 B1 bellek okuması
16’lık tablo (yarım bayt)16 B2 okuma + toplama
POPCNT komutu01 komut (__builtin_popcount)
bits[0..31] (Python ile hesaplandı: bin(i).count("1"))00111223142526371829210311212313314415116217218319220321322423224325326427328429430531bits[0xB7] = bits[183] = 6

Performans

Uzay-Zaman Takası: Renk Paleti

(a) 24 bit/pikselRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGBRGB3 bayt/piksel(b) 8 bit indeks/piksel00110221324435541 bayt/piksel(c) renk paleti0#3b82f61#22a05a2#e9a23b3#e76f514#8b5cf65#14b8a6256 giriş × 3 bayt
1024 × 768 görüntüBoyut (bayt)Oran
(a) 24 bit/piksel2.359.296 (2,25 MiB)1
(b)+(c) 8 bit indeks + palet786.432 + 768 = 787.200≈ 1/3

Yer yaklaşık 3 kat azalır; bedeli her piksel gösterilirken bir tablo bakışı (zaman) ve en fazla 256 renk sınırıdır. GIF ve PNG-8 bu yöntemi kullanır (GIF ayrıca LZW ile sıkıştırır). Boyutlar Python ile hesaplanmıştır.

Performans

Önbelleğe Almak (Caching)

Yol → i-node önbelleği

Yoli-node
/usr6
/usr/ast26
/usr/ast/mbox60
/usr/ast/books92
/usr/bal45
/usr/bal/paper.ps85
  • Önbellek yokken /usr/ast/mbox’ı bulmak: kök i-node’u, kök dizini, /usr i-node’u, /usr dizini, /usr/ast i-node’u, /usr/ast dizini → 6 disk okuması (+ dosyanın i-node’u).
  • Önbellekte tam yol varsa: bir bellek araması, sıfır disk erişimi.
  • Önbellekte yalnızca /usr/ast varsa, arama oradan devam eder: kısmi isabet de kazançtır.
  • Linux: dizin girdisi önbelleği (dcache), i-node önbelleği ve sayfa önbelleği. Boş RAM’in “dolu” görünmesinin nedeni budur.
  • Önbelleğin bedeli: tutarlılık. Dosya silinir veya yeniden adlandırılırsa kayıt geçersiz kılınmalıdır.
Genel kural: aynı sonucu tekrar tekrar hesaplıyorsanız, sonucu saklayın. İşletim sistemindeki önbellekler: TLB, CPU önbellekleri, sayfa önbelleği, dcache, ARP ve DNS önbellekleri.

Performans

İpuçları (Hints)

ipucunu oku“dosya sunucu B’de”doğrulaucuz bir denemedoğruhızlı yol: doğrudan B’ye gityanlışyavaş yol: dizin hizmetine soripucunu güncelle
Önbellekten farkı

Önbellekteki değer her zaman doğru olmalıdır. İpucu yanlış olabilir; bu yüzden geçersiz kılma gerekmez, ama kullanmadan önce ucuz bir doğrulama şarttır.

Örnekler

Dağıtık dosya sisteminde “dosya muhtemelen sunucu B’de”; web’de yönlendirme önbelleği; dal tahmini; uygulamadan çekirdeğe madvise(MADV_SEQUENTIAL) ile verilen erişim ipucu.

Performans

Yerelliği Kullanmak (Exploiting Locality)

ext4 disk düzeni: blok gruplarıblok grubu 0i-nodeveri bloklarıblok grubu 1i-nodeveri bloklarıblok grubu 2i-nodeveri bloklarıi-node ile verisi aynı grupta: kısa aramaCPU yakınlığı (affinity)çekirdek 0L1/L2 önbellekçekirdek 1L1/L2 önbellekçekirdek 2L1/L2 önbellekçekirdek 3L1/L2 önbellekiş parçacığı aynı çekirdekte kalırsa önbelleği “sıcak” kalır
  • Zamansal yerellik: yakın zamanda kullanılan tekrar kullanılır (önbelleğin temeli). Uzamsal yerellik: yakınındaki de kullanılır (önden okuma, büyük sayfalar).
  • Birlikte kullanılan verileri yan yana koymak: FFS silindir grupları, ext4 blok grupları; NUMA’da belleği iş parçacığının düğümünden ayırmak.

Performans · Adım adım

Yaygın Durumu Hızlandırmak

kullanıcı alanıİş parçacığı Akilidi istiyorİş parçacığı Bçalışıyorkilit sözcüğüdeğer = 0çekirdekfutex bekleme kuyruğuboşkilit boş (0)

Kilitlerin büyük çoğunluğu çekişmesiz alınır. Yaygın durum bu ise, hızlandırılması gereken de budur.

kullanıcı alanıİş parçacığı Akilidi aldıİş parçacığı Bçalışıyorkilit sözcüğüdeğer = 1çekirdekfutex bekleme kuyruğuboşCAS 0→1 başarılı: sistem çağrısı yok

A, atomik karşılaştır-değiştir (CAS) ile 0’ı 1 yapar. Çekirdeğe hiç girilmez: birkaç nanosaniye.

kullanıcı alanıİş parçacığı Akritik bölgedeİş parçacığı Buyuyorkilit sözcüğüdeğer = 2çekirdekfutex bekleme kuyruğuBfutex(WAIT)CAS başarısız → 2 “bekleyen var”

Nadir durum: B de kilidi ister, CAS başarısız olur. Değeri 2 yapar ve futex(FUTEX_WAIT) ile çekirdekte uyur. Yavaş yol yalnızca burada.

kullanıcı alanıİş parçacığı Akilidi bıraktıİş parçacığı Buyandıkilit sözcüğüdeğer = 0çekirdekfutex bekleme kuyruğuboşfutex(WAKE)değer 2 idi → uyandır

A bırakırken eski değer 2 ise futex(FUTEX_WAKE) çağırır; 1 olsaydı hiç çağırmazdı. B uyanır ve kilidi alır.

Genel ilke (Lampson): yaygın durumu hızlı, nadir durumu doğru yap. Diğer örnekler: sistem çağrılarının hızlı yolu, vDSO ile çekirdeğe girmeden clock_gettime, TLB isabeti.

Proje Yönetimi · Adım adım

Efsanevi Adam-Ay (The Mythical Man-Month)

12n = 2 kişi → 1 iletişim yolu1n=26n=415n=628n=845n=10yol sayısı = n(n−1)/2

“Adam-ay” (man-month) yanıltıcı bir birimdir: iş, kişiler arasında bölünebilir varsayar. 2 kişi arasında yalnızca 1 iletişim yolu var.

1234n = 4 kişi → 6 iletişim yolu1n=26n=415n=628n=845n=10yol sayısı = n(n−1)/2

4 kişide 6 yol. Her yeni kişi herkesle eşgüdüm kurmak zorunda; toplantı, belge ve arayüz anlaşmaları artar.

123456n = 6 kişi → 15 iletişim yolu1n=26n=415n=628n=845n=10yol sayısı = n(n−1)/2

6 kişide 15 yol. Gecikmiş projeye eklenen kişiyi eğitmek, mevcut ekibin zamanını da tüketir.

12345678n = 8 kişi → 28 iletişim yolu1n=26n=415n=628n=845n=10yol sayısı = n(n−1)/2

8 kişide 28 yol. Brooks yasası: “Gecikmiş bir yazılım projesine eleman eklemek, onu daha da geciktirir.”

Brooks’un OS/360 deneyiminden önerdiği zaman dağılımı: 1/3 planlama, 1/6 kodlama, 1/4 modül testi, 1/4 sistem testi. Yani kod yazmak işin yalnızca altıda biridir.

Proje Yönetimi

Takım Yapısı, Deneyim ve “Gümüş Kurşun Yok”

Linus Torvaldsağ bakımcısıbellek bakımcısıdosya sistemi bakımcısıağ sürücüsü bakımcısımm alt alanı bakımcısıext4 bakımcısıbinlerce katkıcının yamaları yukarı akar (yılda ~4-5 bin geliştirici)
Takım yapısı

Mills/Brooks’un cerrah ekibi: baş programcı tasarlar ve kodlar, diğerleri destekler. Kavramsal bütünlük birkaç kişide kalır.

Deneyimin rolü

İyi programcı ortalamadan kat kat verimlidir. “Birini atmayı planlayın”; ikinci sistem etkisine dikkat.

Gümüş kurşun yok

Brooks (1986): araçlar yalnız arızi karmaşıklığı azaltır, özsel karmaşıklık kalır. Yapay zekâ destekli kodlama da tasarım sorumluluğunu kaldırmaz.

Eğilimler

İşletim Sistemlerinde Eğilimler

Eğilimİşletim sistemine etkisi
Sanallaştırma ve bulutHipervizör, konteyner, mikro-VM (Firecracker); çok kiracılı yalıtım
Çok çekirdekli yongalarÖlçeklenebilir kilitler, RCU, NUMA farkındalığı, heterojen çekirdekler
Geniş adres uzayı64 bit, 5 düzeyli sayfa tabloları; tek adres uzaylı sistem fikirleri
Kesintisiz veri erişimiAğ, bulut depolama ve yerel disk arasında şeffaf erişim; NVMe, CXL bellek
Pille çalışan sistemlerDVFS, “hızla bitir ve uyu” (race-to-idle), Android Doze, enerji farkında zamanlama (EAS)
Gömülü ve sensör düğümleriGerçek zamanlı küçük çekirdekler: Zephyr, FreeRTOS, Contiki-NG; kilobaytlarca bellek
Güvenli diller ve programlanabilir çekirdekLinux’ta Rust (6.1’den beri), eBPF ve sched_ext, unikernel’ler
Eski listedeki “ağ işlemleri”, “paralel ve dağıtık sistemler” ve “çoklu ortam” artık her sistemin olağan parçası olduğu için ayrı eğilim olarak değil, ilgili satırların içinde ele alındı.

Eğilimler

Sanallaştırma ve Bulut

Sanal makine 1OfficeWindowskonuk işletim sistemiSanal makine 2web sunucusuLinuxkonuk işletim sistemiSanal makine 3veritabanıLinuxkonuk işletim sistemiSanal makine 4güvenlik duvarıFreeBSDkonuk işletim sistemiHipervizör (tip 1: KVM, Xen, Hyper-V, ESXi)Donanım: VT-x / AMD-V, EPT/NPT, IOMMU
  • Sunucu birleştirme, hızlı taşıma, anlık görüntü; bulutun temeli.
  • İşletim sistemi tasarımına etkisi: konuk sistem sanal ortamda olduğunu bilir (paravirtio sürücüleri).
  • Konteynerler çekirdeği paylaşır: daha hafif, daha zayıf yalıtım.
  • Mikro-VM’ler (Firecracker, AWS Lambda): VM yalıtımı, milisaniyede açılış.

Eğilimler

Çok Çekirdek ve Geniş Adres Uzayları

32 bit2³² B = 4 GiB48 bit (4 düzeyli sayfa tablosu)2⁴⁸ B = 256 TiB57 bit (5 düzeyli, LA57)2⁵⁷ B = 128 PiBsanal adres uzayı (çubuk uzunluğu = adres bit sayısı; her bit boyutu ikiye katlar)
Çok çekirdekli yongalar

Sunucularda yuva başına 128-192 çekirdek, telefonlarda büyük/küçük (big.LITTLE) karışık çekirdekler. Tek bir büyük çekirdek kilidi ölçeklenmez: ince taneli kilitler, RCU, çekirdek başına veri yapıları gerekir.

Geniş adres uzayları

Tüm dosyaları belleğe eşlemek (mmap) ya da tek adres uzaylı sistemler mümkün olur. Bedeli: daha derin sayfa tablosu yürüyüşü, daha fazla TLB baskısı.

Eğilimler

Rust, eBPF ve Unikernel’ler

Geleneksel yığınUygulamakütüphanelergenel amaçlı işletim sistemihipervizörUnikernelUygulama + yalnız gerekenOS kütüphaneleri, tek adres uzayıMB’lık tek görüntü, ms’de açılışhipervizör
Rust ile çekirdek

Linux 6.1 (Aralık 2022) ile Rust desteği ana dala girdi, ardından ilk Rust sürücüleri geldi. Amaç: kullanım-sonrası-serbest bırakma ve taşma gibi bellek hatalarını derlemede önlemek. Windows çekirdeğinde de Rust bileşenleri var.

eBPF

Doğrulanmış küçük programlarla çekirdeği yeniden derlemeden genişletmek: izleme, ağ (XDP), güvenlik, zamanlama (sched_ext).

Unikernel

Exokernel’in libOS fikrinin bulut sürümü: MirageOS, Unikraft. Tek uygulamalı mikro hizmetler için.

Özet

Özet

KonuAna fikir
ZorluklarBoyut, eşzamanlılık, düşman kullanıcılar, uzun ömür, uyumluluk
HedeflerSoyutlama, ilkel işlemler, yalıtım, donanım yönetimi
ArayüzBasit, bütün, verimli; az ve genel sistem çağrısı
YapıKatmanlı, exokernel, mikroçekirdek, genişletilebilir, çekirdek iş parçacıkları
İlkelerMekanizma/politika, diklik, iki düzeyli ad, geç bağlama
TekniklerDonanımı gizle, dolaylılık, yeniden girişlilik, önce hata denetimi
PerformansÖlç; uzay-zaman takası, önbellek, ipucu, yerellik, yaygın durum
ProjeBrooks yasası, küçük güçlü takımlar, gümüş kurşun yok
EğilimlerBulut, çok çekirdek, enerji, Rust, eBPF, unikernel

Özet

Kontrol Soruları

  1. Tanenbaum’a göre işletim sistemi tasarımını zorlaştıran sekiz etkenden dördünü açıklayın.
  2. Basitlik, bütünlük ve verimlilik ilkelerini birer sistem çağrısı örneğiyle tartışın.
  3. Algoritmik ve olay güdümlü yürütme paradigmalarını karşılaştırın. Olay döngüsünde uzun süren bir işleyici neden sorun olur?
  4. Exokernel ile sanal makine monitörü arasındaki temel fark nedir?
  5. Mikroçekirdekte bir sürücü çöktüğünde ne olur? Monolitik çekirdekte aynı durum neden daha tehlikelidir?
  6. Mekanizma ile politikayı ayırmayı zamanlayıcı örneğiyle açıklayın. sched_ext bu ilkeyi nasıl uygular?
  7. /usr/ast/mbox yolunun çözümlenmesi önbelleksiz kaç disk erişimi gerektirir? Önbellek ile ipucu arasındaki fark nedir?
  8. Bit sayma örneğinde döngü, makro ve tablo yöntemlerini yer ve zaman açısından karşılaştırın.
  9. futex neden yaygın durumu hızlandırmanın iyi bir örneğidir?
  10. Brooks yasasını iletişim yolu sayısıyla gerekçelendirin: 10 kişilik ekipte kaç yol vardır?
Cevaplar
  1. Örn. devasa boyut, eşzamanlılık, düşmanca kullanıcılar, yalıtıma rağmen paylaşım, uzun ömür, genellik, taşınabilirlik, geriye dönük uyumluluk.
  2. Basitlik: UNIX’in az sayıda çağrısı; bütünlük: exec ailesinin tek execve ile her ihtiyacı karşılaması; verimlilik: lseek ucuz, read pahalı; maliyet sezilebilmeli.
  3. Algoritmik: akışı program belirler. Olay güdümlü: dış olaylar belirler. Tek iş parçacıklı döngüde uzun işleyici bitene kadar diğer olaylar işlenemez, arayüz donar.
  4. VM’e makinenin tam bir kopyası verilir; exokernel kaynakları bölüştürür, kimin neye sahip olduğunu izler, yeniden eşleme gerekmez; soyutlamaları libOS sağlar.
  5. Yalnız sürücü süreci ölür; yeniden doğuş sunucusu onu yeniden başlatır. Monolitik çekirdekte sürücü çekirdek adres uzayındadır; hatası tüm sistemi çökertir.
  6. Çekirdek “en yüksek öncelikliyi seç” mekanizmasını sunar; öncelikleri uygulama belirler. sched_ext ile politika eBPF programı olarak yüklenir, çekirdek mekanizması aynı kalır.
  7. 6 okuma (3 i-node + 3 dizin bloğu), dosyanın i-node’u ile 7. Önbellek her zaman doğrudur; ipucu yanlış olabilir, kullanmadan önce doğrulanır.
  8. Döngü: yer yok, 8 tur. Makro: yer yok, dal yok ama ~24 komut. Tablo: 256 bayt, tek okuma. Donanımda POPCNT tek komuttur.
  9. Çekişmesiz kilit kullanıcı alanında tek atomik işlemle alınır; çekirdeğe yalnız nadir çekişme durumunda girilir.
  10. 10·9/2 = 45 yol. Eklenen her kişi iletişim yükünü karesel artırır ve eğitim için mevcut ekibin zamanını tüketir.

Özet

Kaynaklar

  • A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4. baskı (2014) / 5. baskı (2022), Pearson — Bölüm 12: Operating System Design.
  • B. W. Lampson, “Hints for Computer System Design”, ACM SOSP, 1983 (ve 2020 güncellemesi “Hints and Principles for Computer System Design”).
  • F. P. Brooks Jr., The Mythical Man-Month: Essays on Software Engineering, 20. yıl baskısı, Addison-Wesley, 1995 — “No Silver Bullet” (1986) dahil.
  • J. H. Saltzer, M. F. Kaashoek, Principles of Computer System Design: An Introduction, Morgan Kaufmann, 2009.
  • D. R. Engler, M. F. Kaashoek, J. O’Toole, “Exokernel: An Operating System Architecture for Application-Level Resource Management”, SOSP 1995.
  • G. Klein vd., “seL4: Formal Verification of an OS Kernel”, SOSP 2009; J. N. Herder vd., MINIX 3 güvenilirlik çalışmaları.
  • Linux çekirdeği belgeleri: Rust (docs.kernel.org/rust), BPF ve sched_ext; H. Franke vd., “Fuss, Futexes and Furwocks”, 2002.

Son

Bölüm 15: İşletim Sistemi Tasarımı
Sonraki bölüm: Linux
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.