Hazırlayan: Enes DURMAZ
Siber Güvenliğin Yazılım Temelleri: Donanım ile Uygulama Arasındaki Katmanı Anlamak
Bir önceki çalışmada bilgisayarın fiziksel anatomisini, yani CPU, RAM, depolama birimlerini ve anakart veri yollarını inceledik. Ancak donanım tek başına yalnızca elektrik sinyallerinden ibarettir. Bu sinyalleri düzenli, güvenli ve verimli bir çalışma ortamına dönüştüren katman işletim sistemidir (Operating System — OS).
Siber güvenlik açısından işletim sistemi, sistemin hakemidir: hangi programın ne kadar CPU süresi alacağına, hangi sürecin hangi bellek adresini görebileceğine ve hangi kullanıcının hangi kaynağa dokunabileceğine karar verir. Yetki yükseltme (privilege escalation), süreç enjeksiyonu (process injection), bellek taşmaları ve bellek adli bilişimi gibi konuların hepsi bu hakemin kurallarını ya anlamaya ya da aşmaya dayanır.
Süreçlerin nasıl doğduğunu, nasıl zamanlandığını ve belleğin nasıl paylaştırıldığını bilmeyen biri, bir zararlı yazılımın sistemde ne yaptığını da, bir bellek bozulması zafiyetinin neden tehlikeli olduğunu da gerçekten kavrayamaz.
Bu çalışma; işletim sistemi çekirdeğinin çalışma mantığını, süreç ve iş parçacığı (thread) yönetimini, CPU zamanlamasını ve süreç bellek yapılarını siber güvenlik perspektifiyle ele almaktadır.
İçindekiler
- 1. İşletim Sistemine Giriş
- 2. İşletim Sistemi Çekirdeği ve Çalışma Mantığı
- 3. Süreç (Process) Yönetimi
- 4. CPU Zamanlama, Bağlam Değişimi ve Eşzamanlılık
- 5. Bellek Yönetimi ve Süreç Bellek Yapıları
- 6. Temel İşletim Sistemi Kavramlarının Karşılaştırmalı Özeti
- 7. Sonuç ve İşletim Sistemi Perspektifinden Siber Güvenlik
- 8. Soru Bankası
1. İşletim Sistemine Giriş
Bir önceki bölümde gördüğümüz gibi donanım; işlemci, bellek, depolama ve veri yollarından oluşur. Ancak bu bileşenleri doğrudan programlamak son derece zahmetlidir: her program kendi disk sürücüsünü, kendi ekran çıkışını ve kendi bellek yönetimini yazmak zorunda kalırdı. Üstelik aynı anda çalışan iki program birbirinin belleğini ezebilir, aynı diske aynı anda yazmaya çalışıp veriyi bozabilirdi.
İşletim sistemi bu sorunları çözmek için üç temel görevi üstlenir:
- Soyutlama (Abstraction): Karmaşık donanımı basit kavramlara çevirir. Disk sektörleri "dosya", fiziksel RAM "sanal adres uzayı", CPU zamanı "süreç" haline gelir.
- Kaynak Yönetimi (Resource Management): CPU süresi, bellek, disk ve ağ gibi sınırlı kaynakları rekabet eden programlar arasında adil ve verimli biçimde paylaştırır.
- Koruma ve İzolasyon (Protection & Isolation): Programları birbirinden ve çekirdekten ayırır, yetkisiz erişimi donanımın desteğiyle engeller.
Bu üçüncü görev, siber güvenliğin kalbidir. İşletim sisteminin güvenlik modeli temelde şu soruya dayanır: "Bu süreç, bu kaynağa, bu işlemi yapmaya yetkili mi?" Saldırganın amacı ise çoğu zaman bu sorunun cevabını kendi lehine değiştirmektir.
İşletim sisteminin gözünde çalışan her şey bir süreçtir (process) ve her sürecin kendine ait bir bellek dünyası vardır. Bu iki kavram, bu yazının omurgasını oluşturur.

2. İşletim Sistemi Çekirdeği ve Çalışma Mantığı
2.1. İşletim Sisteminin Görevleri ve Katmanlı Yapı
İşletim sistemi tek bir parça değil, katmanlardan oluşan bir bütündür. Aşağıdan yukarıya doğru tipik yapı şöyledir:

Çekirdek (Kernel), işletim sisteminin her zaman bellekte bulunan ve en yüksek ayrıcalıkla çalışan çekirdek parçasıdır. Süreç yönetimi, bellek yönetimi, dosya sistemi, aygıt sürücüleri ve ağ yığını gibi temel hizmetleri sunar. Kullanıcı arayüzü, komut satırı kabuğu (shell) ve sıradan programlar çekirdeğin parçası değil, onun hizmetlerinin müşterileridir.
2.2. Kullanıcı Modu, Çekirdek Modu ve Sistem Çağrıları (System Calls)
Bir önceki yazıda x86 koruma halkalarını (Ring 0 ve Ring 3) görmüştük. İşletim sistemi bu donanım özelliğini şu şekilde kullanır:
- Kullanıcı Modu (User Mode, Ring 3): Sıradan uygulamaların çalıştığı kısıtlı moddur. Bu moddaki bir program donanıma doğrudan dokunamaz, başka bir sürecin belleğini okuyamaz ve ayrıcalıklı CPU komutlarını çalıştıramaz. Yasak bir işlem denendiğinde CPU bir istisna (exception) üretir ve işletim sistemi devreye girerek programı genellikle sonlandırır.
- Çekirdek Modu (Kernel Mode, Ring 0): Çekirdek ve aygıt sürücülerinin çalıştığı, tüm belleğe ve donanıma erişimi olan moddur.

Peki bir uygulama dosya açmak ya da ağa bağlanmak gibi ayrıcalık gerektiren bir işi nasıl yapar? Cevap sistem çağrısıdır (system call). Uygulama, çekirdekten hizmet isteyen kontrollü bir kapı kullanır:
- Uygulama
fopen()gibi bir kütüphane fonksiyonunu çağırır. - Kütüphane, istenen sistem çağrısının numarasını ve parametrelerini yazmaçlara yerleştirir (Linux x86_64'te çağrı numarası
RAXyazmacına konur). syscallkomutu çalıştırılır. CPU, kullanıcı modundan çekirdek moduna donanımsal olarak geçer ve yürütmeyi çekirdeğin önceden belirlenmiş giriş noktasına yönlendirir.- Çekirdek, isteğin geçerli ve yetkili olup olmadığını denetler, işi yapar ve sonucu döndürür.
- CPU kullanıcı moduna geri döner ve program kaldığı yerden devam eder.
Kritik nokta şudur: uygulama çekirdek koduna kendi seçtiği bir adrese atlayamaz. Giriş noktasını çekirdek belirler. Bu, korumanın temelidir.
| İşlem | Linux Sistem Çağrısı | Windows Karşılığı (Win32 / Native API) |
|---|---|---|
| Dosya açma | open / openat | CreateFile / NtCreateFile |
| Dosya okuma | read | ReadFile / NtReadFile |
| Süreç oluşturma | fork / clone + execve | CreateProcess / NtCreateUserProcess |
| Bellek ayırma | mmap / brk | VirtualAlloc / NtAllocateVirtualMemory |
| Süreç sonlandırma | exit / kill | ExitProcess / TerminateProcess |
2.3. Çekirdek Mimarileri: Monolitik, Mikro Çekirdek ve Hibrit Yapılar
Çekirdeğin hangi hizmetleri Ring 0'da çalıştıracağı bir tasarım tercihidir:
- Monolitik Çekirdek (Linux): Süreç yönetimi, bellek yönetimi, dosya sistemleri ve sürücülerin büyük kısmı tek bir büyük program olarak çekirdek modunda çalışır. Bileşenler arası çağrılar hızlıdır, ancak herhangi bir bileşendeki hata tüm sistemi çökertebilir. Linux, ihtiyaca göre yüklenip kaldırılabilen çekirdek modülleri ile bu yapıya esneklik katar.
- Mikro Çekirdek (Microkernel): Çekirdekte yalnızca en temel hizmetler (zamanlama, temel bellek yönetimi, süreçler arası iletişim) kalır. Dosya sistemi ve sürücüler kullanıcı modunda ayrı süreçler olarak çalışır. Bir sürücü çökerse sistem ayakta kalabilir ve saldırı yüzeyi küçülür; bedel ise artan iletişim yüküdür. QNX ve seL4 bu yaklaşımın örnekleridir.
- Hibrit Çekirdek (Windows NT, macOS XNU): İki yaklaşımın karışımıdır. Mikro çekirdekten esinlenen modüler bir tasarım kullanılır, ancak performans için birçok hizmet çekirdek modunda tutulur.
2.4. Çekirdek Düzeyinde Güvenlik: Sürücüler, Rootkit'ler ve Ayrıcalık Yükseltme

Siber Güvenlik Bağlantısı: Çekirdek Güvenliği
- Ayrıcalık Yükseltme (Privilege Escalation): Saldırganlar çoğu zaman sisteme önce düşük yetkili bir kullanıcı olarak girer. Asıl hedef, yetkiyi yükselterek yönetici/root hakkı veya doğrudan çekirdek düzeyinde kod çalıştırma yeteneği kazanmaktır. Çekirdekteki, çekirdek modülündeki veya sürücüdeki tek bir bellek bozulması zafiyeti, tüm koruma duvarlarının aşılmasına yol açabilir.
- Aygıt Sürücüleri: En Zayıf Halka: Sürücüler Ring 0'da çalışır ve genellikle üçüncü taraflarca yazılır. Zafiyetli ama geçerli imzaya sahip bir sürücünün sisteme yüklenmesi (BYOVD — Bring Your Own Vulnerable Driver), saldırganlara çekirdek erişimi kazandırmak için bilinen bir tekniktir. Bu nedenle Windows, Microsoft tarafından engellenen zafiyetli sürücülerin listesini tutar.
- Rootkit'ler: Çekirdek düzeyinde çalışan rootkit'ler, işletim sisteminin kendi sistem çağrısı sonuçlarını değiştirerek kendilerini süreç listesinden, dosya listesinden ve ağ bağlantılarından gizler. Güvenlik yazılımı, "yalan söyleyen" bir çekirdeğe güvenmek zorunda kaldığı için bu tehditleri görmek zorlaşır.
- Savunma Katmanları: Modern sistemler çekirdek kodunu korumak için SMEP/SMAP (çekirdeğin kullanıcı belleğindeki kodu çalıştırmasını ve gelişigüzel okumasını engelleyen CPU özellikleri), imzalı sürücü zorunluluğu, çekirdek bütünlük korumaları ve KPTI (Meltdown'a karşı çekirdek ve kullanıcı sayfa tablolarını ayıran yama) gibi mekanizmalar kullanır.
3. Süreç (Process) Yönetimi
3.1. Program, Süreç ve İş Parçacığı (Thread) Kavramları
Üç kavram sıkça karıştırılır:
- Program: Diskte duran pasif bir dosyadır (örneğin
chrome.exeveya/bin/ls). İçinde makine kodu ve veri bulunur, kendi başına hiçbir şey yapmaz. - Süreç (Process): Çalışmakta olan bir programın örneğidir. Programın kodunun yanı sıra kendi sanal adres uzayını, açık dosya tutamaçlarını, kimlik bilgilerini (kullanıcı, yetkiler) ve en az bir iş parçacığını barındırır. Aynı programdan aynı anda birden fazla süreç çalışabilir.
- İş Parçacığı (Thread): Bir süreç içindeki yürütme birimidir. Her thread'in kendi program sayacı (RIP), yazmaç kümesi ve yığını (stack) vardır; ancak aynı sürecin thread'leri kod, global veri ve heap alanını paylaşır.

| Özellik | Süreç (Process) | İş Parçacığı (Thread) |
|---|---|---|
| Adres uzayı | Her sürecin kendine ait, yalıtılmış | Aynı sürecin thread'leri ortak kullanır |
| Oluşturma maliyeti | Yüksek | Düşük |
| Bağlam değişimi maliyeti | Yüksek (adres uzayı değişir) | Düşük (adres uzayı aynı kalır) |
| İletişim | IPC mekanizmaları gerekir | Ortak belleği doğrudan kullanır |
| Bir hatanın etkisi | Genellikle yalnızca o süreç çöker | Tüm sürece zarar verebilir |
Süreçlerin yalıtımı güvenlik sağlar, thread'lerin ortak belleği ise hız sağlar. Her ikisi de bir bedelle gelir: ortak bellek, eşzamanlılık hatalarının kaynağıdır (bkz. Bölüm 4).
3.2. Süreç Kontrol Bloğu (PCB) ve Süreç Durumları
İşletim sistemi her süreci Süreç Kontrol Bloğu (Process Control Block — PCB) adı verilen bir çekirdek veri yapısıyla izler. Linux'ta bu yapı task_struct, Windows'ta EPROCESS ve ETHREAD yapılarıdır. Bir PCB tipik olarak şunları içerir:
- Süreç Kimliği (PID) ve üst sürecin kimliği (PPID)
- Süreç durumu (hazır, çalışıyor, bekliyor vb.)
- Kaydedilmiş CPU yazmaçları ve program sayacı (bağlam değişimi için)
- Bellek yönetim bilgisi: sayfa tablosunun konumu, bellek bölgeleri
- Açık dosya ve tutamaç tablosu
- Güvenlik kimliği: kullanıcı (UID/SID), grup, yetkiler (capabilities/token)
- Zamanlama bilgisi: öncelik, harcanan CPU süresi
Bir süreç ömrü boyunca şu durumlar arasında gidip gelir:

- Yeni (New): Süreç oluşturuluyor.
- Hazır (Ready): CPU'ya atanmayı bekliyor.
- Çalışıyor (Running): Şu an bir CPU çekirdeğinde yürütülüyor.
- Bekliyor (Waiting/Blocked): Bir G/Ç işleminin tamamlanmasını veya bir olayı bekliyor.
- Sonlandı (Terminated): Çalışmasını bitirdi; kaynakları geri alınıyor.
Linux'ta ps ve top çıktılarında görülen karşılıkları ise şöyledir: R (çalışıyor/hazır), S (kesilebilir uyku), D (kesilemez uyku, genellikle disk G/Ç), T (durdurulmuş) ve Z (zombi).
3.3. Süreç Oluşturma: fork, exec ve CreateProcess
Süreçler boşluktan doğmaz; mutlaka başka bir süreç tarafından oluşturulur. Bu bir ebeveyn–çocuk (parent–child) ağacı oluşturur. Linux'ta ağacın kökü init/systemd (PID 1) sürecidir.
Linux (UNIX) yaklaşımı iki adımlıdır:
fork(): Çağıran sürecin neredeyse birebir kopyası olan bir çocuk süreç oluşturur. Verimlilik için Copy-on-Write (CoW) kullanılır: bellek sayfaları başlangıçta fiziksel olarak kopyalanmaz, ebeveyn ve çocuk aynı sayfaları paylaşır. Taraflardan biri bir sayfaya yazmaya kalkarsa o sayfa o anda kopyalanır.exec()ailesi: Çocuk sürecin belleğini yeni bir programla değiştirir. Süreç kimliği aynı kalır, ancak içinde artık başka bir program çalışır.
Bir kabukta ls yazdığınızda olan tam olarak budur: kabuk kendini fork eder, çocuk exec("/bin/ls") çağırır, ebeveyn ise çocuğun bitmesini wait() ile bekler.
Windows yaklaşımı tek adımlıdır: CreateProcess() hem yeni süreci oluşturur hem de belirtilen programı içine yükler. Windows'ta süreç ağacı UNIX kadar katı bir kavram değildir; ancak ebeveyn bilgisi yine de kayıt altında tutulur ve güvenlik analizinde (örneğin winword.exe sürecinin powershell.exe başlatması gibi şüpheli ilişkilerde) çok değerlidir.
Süreç sonlanması: Bir süreç exit() ile ya da bir sinyal/istisna yüzünden biter. Çocuk sonlandığında çıkış durumunu ebeveyne bildirmek zorundadır; ebeveyn bunu wait() ile okuyana kadar çocuğun PCB kaydı bellekte kalır. Bu durum zombi süreç olarak adlandırılır.
4. CPU Zamanlama, Bağlam Değişimi ve Eşzamanlılık
Bilgisayarda aynı anda onlarca, yüzlerce süreç "çalışıyor" görünür; oysa bir CPU çekirdeği her an yalnızca bir iş parçacığını yürütebilir. Bu yanılsama, CPU zamanının çok kısa dilimlere bölünerek sürekli el değiştirmesiyle yaratılır.
4.1. Bağlam Değişimi (Context Switch)
CPU'nun bir iş parçacığından diğerine geçmesine bağlam değişimi (context switch) denir. İşlem sırasında çekirdek:
- Çalışan thread'in yazmaçlarını ve program sayacını kendi PCB/thread yapısına kaydeder.
- Zamanlayıcının seçtiği yeni thread'in kayıtlı durumunu CPU yazmaçlarına yükler.
- Farklı bir sürece geçiliyorsa adres uzayını değiştirir (sayfa tablosu işaretçisini günceller; bu da TLB önbelleğinin etkilenmesine yol açar).
Bu işlem tipik olarak mikrosaniye mertebesindedir; sık yapıldığında bile sistemin hızını belirgin biçimde düşürebilir, çünkü bağlam değişimi "faydalı iş" üretmez ve önbellekleri soğutur.

Geçişi tetikleyen olaylar şunlardır: zaman diliminin dolması (donanım zamanlayıcı kesmesi sayesinde çekirdek CPU'yu geri alır), sürecin G/Ç için beklemeye geçmesi, daha yüksek öncelikli bir sürecin hazır hale gelmesi veya sürecin gönüllü olarak CPU'yu bırakması.
4.2. Zamanlama Algoritmaları
Zamanlayıcı (Scheduler), hazır kuyruğundaki thread'lerden hangisinin CPU'yu alacağına karar verir. Hedefler birbiriyle çelişebilir: yüksek verim, düşük bekleme süresi, hızlı tepki ve adalet.
| Algoritma | Çalışma Mantığı | Güçlü Yanı | Zayıf Yanı |
|---|---|---|---|
| FCFS (İlk Gelen İlk Hizmet Alır) | Gelen sırayla çalıştırır, kesmez. | Basit | Uzun bir iş, arkadakileri bekletir (convoy etkisi). |
| SJF (En Kısa İş Önce) | Tahmini en kısa işi seçer. | Ortalama bekleme süresi optimumdur. | Süreyi önceden bilmek zordur; uzun işler aç kalabilir. |
| Round Robin | Herkese sırayla sabit bir zaman dilimi (quantum) verir. | Adil, etkileşimli sistemlere uygun | Dilim çok küçükse bağlam değişimi yükü artar. |
| Öncelik Tabanlı | En yüksek öncelikliyi çalıştırır. | Kritik işler hızlı çalışır. | Düşük öncelikliler açlık (starvation) yaşayabilir; çözümü "yaşlandırma (aging)". |
| MLFQ (Çok Seviyeli Geri Beslemeli Kuyruk) | Davranışa göre süreçleri kuyruklar arasında taşır. | Kısa/etkileşimli işlere öncelik verir. | Ayarlaması karmaşıktır. |
Gerçek sistemlerde bu fikirlerin karma biçimleri kullanılır:
- Linux: Uzun yıllar CFS (Completely Fair Scheduler) kullanıldı; her sürece "adil CPU payı" vermeye çalışır. Linux 6.6 sürümünden itibaren yerini EEVDF zamanlayıcısı almıştır.
- Windows: Öncelik tabanlı, kesintili (preemptive) bir zamanlayıcı kullanır; 0–31 arası öncelik seviyeleri vardır ve en yüksek öncelikli hazır thread çalışır. Zamanlama biriminin süreç değil thread olduğuna dikkat edilmelidir.
4.3. Süreçler Arası İletişim (IPC) ve Senkronizasyon
Süreçler birbirinden yalıtılmıştır; ancak çoğu zaman iş birliği yapmaları gerekir. İşletim sistemi bunun için IPC (Inter-Process Communication) mekanizmaları sunar:
- Pipe (Boru): Bir sürecin çıktısını diğerinin girdisine bağlar (
ls | grep txt). - Paylaşımlı Bellek (Shared Memory): İki sürecin adres uzayına aynı fiziksel sayfaları eşler; en hızlı yöntemdir ancak senkronizasyon geliştiricinin sorumluluğundadır.
- Mesaj Kuyrukları ve Soketler: Yapılandırılmış mesajlaşma ve ağ üzerinden iletişim sağlar.
- Sinyaller (Signals): Bir sürece asenkron olay bildirir (
SIGTERM,SIGKILL,SIGSEGV).
Birden fazla thread veya süreç ortak veriye eriştiğinde senkronizasyon gerekir. Başlıca araçlar şunlardır:
- Mutex (Karşılıklı Dışlama Kilidi): Kritik bölgeye aynı anda yalnızca tek thread'in girmesini sağlar.
- Semafor: Sınırlı sayıda kaynağa erişimi sayaçla denetler.
- Monitör ve koşul değişkenleri: Daha yüksek seviyeli bekleme/uyandırma yapıları sunar.
Yanlış kullanım iki klasik soruna yol açar:
- Yarış Durumu (Race Condition): Sonucun, thread'lerin çalışma sırasının zamanlamasına bağlı olması.
- Kilitlenme (Deadlock): İki veya daha fazla thread'in birbirinin elindeki kilidi sonsuza kadar beklemesi. Kilitlenme için dört koşulun (Coffman koşulları) aynı anda sağlanması gerekir: karşılıklı dışlama, tut ve bekle, öncelikle kesilememe ve dairesel bekleme. Bunlardan biri kırılırsa kilitlenme önlenir. Örneğin tüm kilitlerin her zaman aynı sırayla alınması dairesel beklemeyi engeller.
4.4. Eşzamanlılık Güvenliği: Race Condition ve TOCTOU
Siber Güvenlik Bağlantısı: Zamanlamadan Doğan Zafiyetler
- Yarış Durumu Zafiyetleri: Zamanlama penceresi, saldırganın yararlanabileceği bir zafiyete dönüşebilir. Çok thread'li bir uygulamada paylaşılan değişkenin kilitsiz güncellenmesi; bakiye, yetki veya sayaç değerlerinin tutarsızlaşmasına neden olabilir. Web uygulamalarında aynı kuponun veya işlemin eşzamanlı isteklerle birden fazla kez kullanılması buna bir örnektir.
- TOCTOU (Time-of-Check to Time-of-Use): Bir kaynağın güvenliği kontrol edilir, ancak kullanıldığı ana kadar geçen kısa sürede değiştirilebilir. Örneğin bir programın "bu dosya kullanıcıya ait mi?" kontrolünden sonra, açma işleminden önce dosyanın başka bir hedefe (sembolik bağa) çevrilmesi, yetkili bir programın yetkisiz bir dosyayı işlemesine yol açabilir. Savunma, kontrol ve kullanımı atomik hale getirmek ve kontrol edilen nesneyi tutamaç (handle) üzerinden kullanmaktır.
- Zamanlama Tabanlı Yan Kanallar: Bir önceki yazıda gördüğümüz Spectre ve Meltdown gibi saldırılar, CPU'nun ve zamanlayıcının paylaşımlı kaynak davranışlarını ölçmeye dayanır; işletim sistemi bu nedenle çekirdek–kullanıcı sayfa tablosu ayrımı (KPTI) gibi yazılımsal önlemler uygular.
- Hizmet Reddi: Zamanlayıcıya yük bindirmek (çok sayıda süreç/thread, CPU'yu tüketen döngüler) sistemi yavaşlatabilir. cgroups, kotalar ve limitler (
ulimit) bu riski azaltır.
5. Bellek Yönetimi ve Süreç Bellek Yapıları
Bir önceki yazıda RAM'i, sanal belleği ve MMU'yu donanım açısından tanımıştık. Bu bölümde aynı konuya işletim sisteminin ve çalışan bir programın gözünden bakıyoruz: bir sürecin belleği nasıl düzenlenir, çekirdek sayfaları nasıl yönetir ve bu yapılar güvenlik açısından neden önemlidir?
5.1. Bir Sürecin Bellek Düzeni: Text, Data, BSS, Heap ve Stack
Her süreç, işletim sisteminin sunduğu sanal adres uzayında sanki tüm belleğin sahibiymiş gibi çalışır. Bu uzay, belirli amaçlara ayrılmış bölgelerden oluşur. Linux x86_64 için sadeleştirilmiş düzen şöyledir (adresler yukarı doğru artar):

| Bölge | İçeriği | Tipik İzinler | Notlar |
|---|---|---|---|
| Text (Code) | Programın makine komutları | Okuma + Çalıştırma (R-X) | Yazılabilir olmamalıdır; aynı programın süreçleri bu sayfaları paylaşabilir. |
| Data | Başlangıç değeri verilmiş global/statik değişkenler | Okuma + Yazma (RW-) | Programın çalıştırılabilir dosyasından yüklenir. |
| BSS | Başlangıç değeri verilmemiş (sıfırlanmış) global/statik değişkenler | Okuma + Yazma (RW-) | Dosyada yer kaplamaz, yalnızca boyutu tutulur. |
| Heap | Çalışma zamanında dinamik ayrılan bellek | Okuma + Yazma (RW-) | Geliştiricinin ayırıp serbest bırakmakla yükümlü olduğu alan. |
| Mmap Bölgesi | Paylaşımlı kütüphaneler, eşlenmiş dosyalar | Bölgeye göre değişir | Her kütüphane kendi text/data bölgeleriyle eşlenir. |
| Stack | Fonksiyon çağrı çerçeveleri, yerel değişkenler, dönüş adresleri | Okuma + Yazma (RW-) | Her thread'in kendi yığını vardır. |
Windows'ta kavramsal düzen benzerdir: yürütülebilir dosyanın (PE) bölümleri (.text, .data, .rdata), DLL'ler, heap'ler ve her thread için yığın bulunur. Ek olarak PEB (Process Environment Block) ve TEB (Thread Environment Block) gibi süreç/thread bilgilerini tutan yapılar kullanıcı adres uzayında yer alır.
5.2. Yığın (Stack) ve Çağrı Çerçeveleri
Stack, LIFO (son giren ilk çıkar) mantığıyla çalışan ve her fonksiyon çağrısında otomatik büyüyüp küçülen bellek bölgesidir. Her fonksiyon çağrısı, stack üzerinde bir çağrı çerçevesi (stack frame) oluşturur. Bir çerçeve tipik olarak şunları içerir:
- Fonksiyon parametreleri (mimariye ve çağrı kuralına göre yazmaçlarda ya da stack'te)
- Dönüş adresi (return address): Fonksiyon bittiğinde yürütmenin nereye döneceği
- Önceki çerçeve işaretçisi (
RBP) - Yerel değişkenler (diziler/tamponlar dahil)
Sadeleştirilmiş bir çerçeve (adresler aşağıdan yukarıya artar, stack aşağı doğru büyür):

Önceki yazıdaki yazmaçlarla bağlantı: RSP yığının tepesini, RBP o anki çerçevenin tabanını, RIP ise çalıştırılacak sonraki komutu gösterir. Fonksiyon ret komutuyla döndüğünde CPU, stack'teki dönüş adresini RIP'e yükler. Bu nedenle dönüş adresi, kontrol akışı açısından son derece değerli bir veridir.
Stack'in özellikleri: tahsis ve serbest bırakma otomatik ve çok hızlıdır, boyutu sınırlıdır (Linux'ta tipik olarak süreç başına 8 MB varsayılan sınır), ve çok derin ya da sonsuz özyineleme stack overflow hatasıyla sonuçlanır.
5.3. Sayfa Değiştirme Algoritmaları ve Thrashing
Fiziksel RAM dolduğunda çekirdek, yeni bir sayfa getirebilmek için bellekteki bir sayfayı çıkarmak (evict) zorundadır. Çıkarılan sayfa değiştirilmişse (dirty bit = 1) önce swap alanına yazılır. Hangi sayfanın çıkarılacağına sayfa değiştirme algoritması karar verir:
- FIFO: En eski sayfayı çıkarır. Basittir ancak sık kullanılan bir sayfayı atabilir; ayrıca daha fazla çerçeve vermenin hata sayısını artırabildiği Belady anomalisi görülebilir.
- Optimal: Gelecekte en geç kullanılacak sayfayı çıkarır. Gelecek bilinemediği için pratikte uygulanamaz; yalnızca kıyaslama ölçütüdür.
- LRU (En Az Yakın Zamanda Kullanılan): Uzun süredir kullanılmayanı çıkarır. İyi sonuç verir ancak tam uygulaması pahalıdır.
- Clock (İkinci Şans): LRU'yu
accessedbiti ile ucuza yaklaşıklar; gerçek sistemlerde yaygın bir temeldir.
Thrashing: Sistem, yeterli RAM olmadığı için zamanının çoğunu sayfaları diske yazıp geri okumakla geçirirse gerçek iş yapamaz hale gelir. CPU boşta görünür, disk ise sürekli meşguldür; sistem aşırı yavaşlar. Çözümleri RAM artırmak, çalışan süreç sayısını azaltmak veya bellek kullanımını düşürmektir. Linux'ta bellek tamamen tükenirse OOM Killer (Out-of-Memory Killer) devreye girer ve sistemi kurtarmak için bazı süreçleri sonlandırır.
6. Temel İşletim Sistemi Kavramlarının Karşılaştırmalı Özeti
Aşağıdaki tablo, yazıda ele alınan temel kavramların işlevlerini ve siber güvenlik boyutundaki kritik risk alanlarını özetler:
| Kavram | Temel Görevi | Önemli Veri Yapısı / Mekanizma | Kritik Güvenlik Konusu / Risk Alanı |
|---|---|---|---|
| Çekirdek (Kernel) | Donanımı yönetmek, kaynakları paylaştırmak, koruma sağlamak | Ring 0, sistem çağrısı arayüzü | Ayrıcalık yükseltme, rootkit, zafiyetli sürücüler (BYOVD) |
| Kullanıcı / Çekirdek Modu | Ayrıcalık seviyelerini ayırmak | CPU halkaları, mod geçişi | Mod sınırının aşılması, çekirdek exploit'leri |
| Sistem Çağrısı | Uygulamaya kontrollü çekirdek hizmeti sunmak | syscall, çağrı tablosu | Sistem çağrısı kancalama (hooking), argüman doğrulama hataları |
| Süreç (Process) | Çalışan programın yalıtılmış örneği | PCB (task_struct / EPROCESS), PID | Süreç enjeksiyonu, anormal süreç ağaçları, yetki belirteci çalma |
| İş Parçacığı (Thread) | Süreç içi yürütme birimi | Thread yapısı, kendi yığını | Ortak bellek kaynaklı yarış durumları |
| Zamanlayıcı (Scheduler) | CPU zamanını paylaştırmak | Hazır kuyruğu, öncelikler, quantum | Kaynak tüketme / hizmet reddi, öncelik manipülasyonu |
| Bağlam Değişimi | CPU'yu bir thread'den diğerine geçirmek | Kayıtlı yazmaç durumu | Yan kanal sızıntıları (paylaşımlı CPU durumu) |
| IPC ve Senkronizasyon | Süreçler arası iletişim ve koordinasyon | Pipe, paylaşımlı bellek, mutex, semafor | Race condition, TOCTOU, deadlock |
| Stack | Fonksiyon çağrı çerçeveleri, yerel değişkenler | RSP, RBP, dönüş adresi | Stack buffer overflow, RIP/dönüş adresi bozulması |
| Heap | Dinamik bellek tahsisi | malloc/free, allocator yapıları | Use-after-free, double free, heap taşması |
| Sanal Bellek ve Sayfa Tabloları | Adres yalıtımı, esnek bellek yönetimi | PTE, MMU, TLB, NX/U-S bitleri | Yanlış izinler, Rowhammer/yan kanal ile PTE manipülasyonu |
| Page Fault Mekanizması | Eksik/yetkisiz sayfa erişimini yönetmek | Page fault istisnası, swap | Swap'teki hassas verilerin kalıntısı, segfault kaynaklı çökmeler |
| ASLR / DEP / Canary | Bellek bozulması saldırılarını zorlaştırmak | Rastgele adresleme, NX biti, kanarya değeri | Bilgi sızıntısıyla aşılabilme; tek başına yetersizlik |
7. Sonuç ve İşletim Sistemi Perspektifinden Siber Güvenlik
İşletim sistemi, donanımın ham gücünü kullanılabilir ve güvenli bir platforma dönüştüren katmandır. Bu çalışmada incelendiği üzere:
- Çekirdek ve çalışma mantığı, kullanıcı modu ile çekirdek modu arasındaki donanımsal sınırın ve sistem çağrılarının, tüm güvenlik modelinin temelini oluşturduğunu; çekirdeğe ve sürücülere yönelik saldırıların neden bu kadar kritik olduğunu,
- Süreç yönetimi, her çalışan programın PCB ile izlenen, kendi kimliği, yetkileri ve adres uzayı olan yalıtılmış bir varlık olduğunu; süreç enjeksiyonu ve anormal süreç ilişkilerinin neden savunmacıların ana izleme noktası olduğunu,
- Zamanlama ve eşzamanlılık, bağlam değişimi, IPC ve senkronizasyonun hem performansın hem de race condition ve TOCTOU gibi ince zafiyetlerin kaynağı olduğunu,
- Bellek yönetimi, sürecin text, data, BSS, heap ve stack bölgelerinin, sayfa tablolarındaki koruma bitlerinin ve page fault mekanizmasının, bellek bozulması saldırılarının ve ASLR, DEP/NX, stack canary gibi savunmaların neden böyle tasarlandığını
anlamamızı sağlamıştır.
Önceki yazıda donanımın sınırlarını öğrenmiştik; bu yazıda o donanım üzerinde işletim sisteminin nasıl kurallar koyduğunu gördük. Bir savunmacı, bir sürecin neden "şüpheli" göründüğünü ancak normalin ne olduğunu bilirse söyleyebilir. Bir araştırmacı, bir bellek zafiyetinin etkisini ancak stack, heap ve sayfa tablosunun nasıl çalıştığını bilirse doğru değerlendirebilir.
Bir sonraki adım olarak bu temeller üzerine dosya sistemleri ve yetkilendirme modelleri, ardından ağ temelleri (OSI/TCP-IP) ve kriptografiye giriş konuları, serinin doğal devamı olacaktır.
8. Soru Bankası
Aşağıdaki sorular, yazıda işlenen konuları bölüm sırasıyla pekiştirmek için hazırlanmıştır.






