Sıfırdan işletim sistemi inşa etmek, yazılım mühendisliğindeki en zorlu ama ödüllendirici deneyimlerden biridir. Sizi bilgisayarların en düşük seviyede gerçekten nasıl çalıştığını anlamaya zorlar.
Neden Bir İşletim Sistemi İnşa Etmeli?
prometheus-os üzerinde çalışmaya başladığımda, amacım bir sonraki Linux’u yaratmak değildi. Her geliştiricinin doğal kabul ettiği temel kavramları anlamaktı:
- CPU talimatları nasıl çalıştırır?
- Bellek ayırdığınızda ne olur?
- Kesintiler (interrupt) nasıl çalışır?
- Çoklu görevi (multitasking) mümkün kılan nedir?
Bu sorular beni assembly dili, donanım spesifikasyonları ve sistem programlamanın tavşan deliğine götürdü ve yazılım hakkında düşünme şeklimi temelden değiştirdi.
Önyükleme Süreci
Her şey bootloader ile başlar. Bir bilgisayarı açtığınızda, BIOS/UEFI diskinizin ilk sektörünü belleğe yükler ve ona atlar. Bu 512 baytlık bootloader giriş noktanızdır:
; bootloader.asm - Birinci aşama bootloader
[BITS 16]
[ORG 0x7C00]
start:
; Segment register'larını ayarla
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
; Diskten kernel'ı yükle
mov ah, 0x02 ; BIOS sektör okuma fonksiyonu
mov al, 10 ; Okunacak sektör sayısı
mov ch, 0 ; Silindir 0
mov cl, 2 ; Sektör 2'den başla
mov dh, 0 ; Kafa 0
mov bx, 0x1000 ; Yükleme adresi
int 0x13 ; BIOS kesmesi
; Kernel'a atla
jmp 0x1000
times 510-($-$$) db 0
dw 0xAA55 ; Önyükleme imzası
Bu küçük kod parçası tüm kernel’ınızı belleğe yüklemekten sorumludur.
Bellek Yönetimi
Herhangi bir işletim sisteminin en kritik bileşenlerinden biri bellek yönetimidir. Hangi bellek sayfalarının kullanımda olduğunu takip etmeniz ve işlemlere ayırma/serbest bırakma hizmetleri sağlamanız gerekir.
class PhysicalMemoryManager {
private:
uint32_t* bitmap;
uint32_t totalPages;
uint32_t usedPages;
public:
void* allocatePage() {
for (uint32_t i = 0; i < totalPages; i++) {
if (!testBit(i)) {
setBit(i);
usedPages++;
return (void*)(i * PAGE_SIZE);
}
}
return nullptr; // Bellek dolu
}
void freePage(void* address) {
uint32_t page = (uint32_t)address / PAGE_SIZE;
clearBit(page);
usedPages--;
}
};
Bitmap yaklaşımı eğitim amaçları için basit ama etkilidir. Prodüksiyon sistemleri buddy allocation gibi daha sofistike algoritmalar kullanır.
Kesinti İşleme
Kesintiler, CPU’nun harici olaylara (klavye girişi, zamanlayıcı tikleri) ve dahili istisnalara (sıfıra bölme, sayfa hatası) nasıl yanıt verdiğidir. Interrupt Descriptor Table (IDT) kurmak çok önemlidir:
struct IDTEntry {
uint16_t offsetLow;
uint16_t selector;
uint8_t zero;
uint8_t typeAttr;
uint16_t offsetHigh;
} __attribute__((packed));
void setupIDT() {
// İstisna işleyicilerini ayarla (0-31)
setIDTEntry(0, (uint32_t)divisionByZeroHandler, 0x08, 0x8E);
setIDTEntry(14, (uint32_t)pageFaultHandler, 0x08, 0x8E);
// IRQ işleyicilerini ayarla (32-47)
setIDTEntry(32, (uint32_t)timerHandler, 0x08, 0x8E);
setIDTEntry(33, (uint32_t)keyboardHandler, 0x08, 0x8E);
// IDT'yi yükle
loadIDT(&idtDescriptor);
}
Öğrenilen Dersler
prometheus-os inşa etmek bana paha biçilmez dersler öğretti:
-
Her soyutlamanın bir maliyeti var: Yüksek seviye diller karmaşıklığı gizler, ama o karmaşıklık hala var. Bunu anlamak sizi daha iyi bir programcı yapar.
-
Donanım affetmez: Uygulama geliştirmesinin aksine, işletim sistemi geliştirmesinin güvenlik ağı yok. Tek bir hata tüm sistemi dondurabilir.
-
Dokümantasyon şart: Intel kılavuzları, OSDev wiki ve diğer kaynaklar can simidinizdır. Bunları baştan sona okuyun.
-
Basit başlayın: Ekrana metin yazdırmayla başlayın. Sonra klavye girişi ekleyin. Sonra bellek yönetimi. Artımlı olarak inşa edin.
Başlamak İçin Kaynaklar
Bu yolculuğa çıkmak istiyorsanız:
- OSDev Wiki: İşletim sistemi geliştirme için kesin kaynak
- Intel Yazılım Geliştirici Kılavuzları: x86 mimarisi için şart
- “Operating Systems: Three Easy Pieces”: Mükemmel teorik temel
- QEMU: Gerçek donanımı sürekli yeniden başlatmadan test için
Sonuç
Bir işletim sistemi inşa etmek sizi web uygulamaları yazarken daha hızlı yapmayacak. Ancak üzerine inşa ettiğimiz soyutlama katmanları için derin bir takdir kazandıracak. Kodunuz ile CPU arasında ne olduğunu anladığınızda, daha düşünceli, daha etkili bir mühendis olursunuz.
Bir dahaki sefere uygulamanızda bellek ayırdığınızda veya bir kesinti işlediğinizde, yüzeyin altında tam olarak ne olduğunu bileceksiniz.