Bölüm 8: Bellek Yönetimi

İşletim Sistemleri
Bellek hiyerarşisiTaban ve limit yazmaçlarıAdres bağlama ve MMU Dinamik yükleme ve bağlamaTakasArdışık tahsis ve uyan algoritmaları Parçalanma, biteşlem, buddySayfalamaTLB ve erişim süresi Hiyerarşik, karma, ters tablolarx86-64 ve büyük sayfalarKesimleme, x86 ve ARMv8
Sercan KÜLCÜ · Giresun Üniversitesi · Bilgisayar Mühendisliği

Giriş

Öğrenme Çıktıları

Soyutlama

Bellek hiyerarşisini, adres uzayı soyutlamasını, koruma ve yer değiştirme problemlerini açıklamak.

Adresler

Derleme, yükleme ve yürütme zamanı bağlamayı; mantıksal/fiziksel adresi ve MMU'nun taban-limit denetimini hesaplamak.

Bağlama

Dinamik yüklemeyi, statik ve dinamik bağlamayı, PLT/GOT ile paylaşımlı kütüphaneleri ve takası tartışmak.

Ardışık tahsis

İlk, sonraki, en iyi, en kötü uyan algoritmalarını uygulamak; iç/dış parçalanmayı, biteşlemi ve buddy sistemini çözümlemek.

Sayfalama

Adresi (p, d) olarak bölmek, sayfa tablosu ve TLB ile çeviri yapmak, etkili erişim süresini hesaplamak.

Gerçek sistemler

Hiyerarşik, karma ve ters tabloları; x86-64 dört/beş seviyeli sayfalamayı, büyük sayfaları, kesimlemeyi ve ARMv8'i karşılaştırmak.

Giriş

Bellek Hiyerarşisi ve Bellek Yöneticisi

  • CPU'nun doğrudan erişebildiği depolama yalnızca yazmaçlar ve ana bellektir; disk ancak G/Ç ile.
  • Bellek birimi yalnızca bir akış görür: adres + okuma ya da adres + veri + yazma. Adresin nereden geldiğini bilmez.
  • Yazmaç bir saat döngüsünde okunur; DRAM erişimi yüzlerce döngü sürer ve CPU durur (stall). Aradaki boşluğu önbellek kapatır.
  • Programcı belleğin sınırsız, hızlı, kalıcı ve korumalı olmasını ister; gerçek çözüm hiyerarşidir.
  • Bellek yöneticisi: boş/dolu alanı izler, süreçlere tahsis eder, geri alır, süreçleri birbirinden korur.
Yazmaçlar< 1 ns~1 KBL1 / L2 önbellek1–5 nsKB–MBL3 önbellek10–20 ns10–100+ MBAna bellek (DRAM)80–120 ns8–512 GBSSD (NVMe)10–100 µsTBHDD / teyp5–10 msTB+hızlı, küçük, pahalıyavaş, büyük, ucuz, kalıcıgecikme / kapasite

Değerler 2026 itibarıyla tipik mertebelerdir; çekirdek ve modele göre değişir. Önbellek donanımca yönetilir, bu bölümün konusu ana bellektir.

Giriş

Soyutlama Olmadan Bellek

  • İlk bilgisayarlarda (1960'lar öncesi ana çerçeveler, 1980'ler öncesi kişisel bilgisayarlar) her program fiziksel belleği doğrudan görürdü: MOV REGISTER1, 1000 fiziksel 1000 adresini okur.
  • Bellekte aynı anda iki program olamaz: ikisi de aynı fiziksel adreslere yazar, biri diğerini ezer.
  • (a) ve (c)'de kullanıcı programındaki bir hata işletim sistemini çökertebilir.
  • (b) bazı gömülü sistemlerde, (c) MS-DOS'lu ilk PC'lerde kullanıldı (BIOS sürücüleri ROM'da).
  • Bugün de MMU'suz mikrodenetleyiciler böyle çalışır; çoğu en azından MPU (bellek koruma birimi) ile bölgeleri korur.
Kullanıcı programıİS (RAM)(a)0İS (ROM)Kullanıcı programı(b)0Sürücüler (ROM)Kullanıcı programıİS (RAM)(c)00xFFF…

Giriş · Adım adım

Yer Değiştirme Problemi

(a) A programıJMP 240ADD4MOV8⋮MOV24ADD28⋮…16380(b) B programıJMP 280MOV REG1, 284ADD8⋮MOV24CMP28⋮…16380ikisi de 0'dan başlayacakşekilde derlendi (16 KB)

A ve B 16 KB'lık iki program; ikisi de 0 adresinden başlayacağı varsayılarak derlendi.

(a) A programıJMP 240ADD4MOV8⋮MOV24ADD28⋮…16380(b) B programıJMP 280MOV REG1, 284ADD8⋮MOV24CMP28⋮…16380(c) ikisi birlikteJMP 240ADD4MOV8⋮MOV24ADD28⋮JMP 2816384MOV REG1, 2816388ADD16392⋮MOV16408CMP16412⋮

İşletim sistemi önce A'yı 0'a, ardından B'yi hemen üstüne, 16384'e yükler.

(a) A programıJMP 240ADD4MOV8⋮MOV24ADD28⋮…16380(b) B programıJMP 280MOV REG1, 284ADD8⋮MOV24CMP28⋮…16380(c) ikisi birlikteJMP 240ADD4MOV8⋮MOV24ADD28⋮JMP 2816384MOV REG1, 2816388ADD16392⋮MOV16408CMP16412⋮A'yaatlar!

B'nin ilk komutu JMP 28 mutlak adres kullanır: fiziksel 28'e, yani A'nın ADD komutuna atlar ve program çöker.

(a) A programıJMP 240ADD4MOV8⋮MOV24ADD28⋮…16380(b) B programıJMP 280MOV REG1, 284ADD8⋮MOV24CMP28⋮…16380(c) ikisi birlikteJMP 240ADD4MOV8⋮MOV24ADD28⋮JMP 1641216384MOV REG1, 2816388ADD16392⋮MOV16408CMP16412⋮+16384

Statik yer değiştirme (IBM 360): yükleyici her adres sözcüğüne başlangıç adresini ekler: JMP 16412. Yükleme yavaşlar.

(a) A programıJMP 240ADD4MOV8⋮MOV24ADD28⋮…16380(b) B programıJMP 280MOV REG1, 284ADD8⋮MOV24CMP28⋮…16380(c) ikisi birlikteJMP 240ADD4MOV8⋮MOV24ADD28⋮JMP 1641216384MOV REG1, 2816388ADD16392⋮MOV16408CMP16412⋮+16384sabit 28 değişmemeli!

Ama MOV REG1, 28'deki 28 bir sabittir, değişmemelidir. Yükleyici hangi sözcüğün adres olduğunu bilmek için ek yer değiştirme bilgisi ister.

Adres Uzayı

Adres Uzayı: Taban ve Limit Yazmaçları

  • Adres uzayı: bir sürecin kullanabileceği adresler kümesi. Her sürecin kendine ait, diğerlerinden bağımsız adres uzayı vardır.
  • Çözülmesi gereken iki problem: koruma (başkasının alanına erişememe) ve yer değiştirme (her yere yüklenebilme).
  • En basit donanım: taban (başlangıç fiziksel adresi) ve limit (uzunluk) yazmaçları. Program bitişik bir alana olduğu gibi yüklenir.
  • Yazmaçlar yalnızca çekirdek kipinde ayrıcalıklı komutlarla yüklenir; bağlam değişiminde yeni sürecin değerleri konur.
  • CDC 6600 böyle çalışıyordu. Intel 8088'in kesim yazmaçları ise yalnızca taban idi; limit olmadığından koruma yoktu.
İşletim sistemi0süreç256000süreç (aktif)300040süreç4209408800001024000300040taban120900limit

Adres Uzayı · Adım adım

Donanımsal Adres Koruması

CPUadres300.040≥ taban ?evet< taban+limit ?Bellekhayırİşletim sistemine tuzak: adresleme hatasıhayırhayırtaban = 300.040limit = 120.900geçerli: 300.040 … 420.939

300.040 = taban: ilk geçerli adres; iki karşılaştırma da geçer, erişim yapılır.

CPUadres356.000≥ taban ?evet< taban+limit ?Bellekhayırİşletim sistemine tuzak: adresleme hatasıhayırhayırtaban = 300.040limit = 120.900geçerli: 300.040 … 420.939

356.000 aralığın içinde; erişim yapılır. Denetim her erişimde, paralel donanımla yapılır.

CPUadres420.939≥ taban ?evet< taban+limit ?Bellekhayırİşletim sistemine tuzak: adresleme hatasıhayırhayırtaban = 300.040limit = 120.900geçerli: 300.040 … 420.939

420.939 = taban + limit − 1: son geçerli adres.

CPUadres420.940≥ taban ?evet< taban+limit ?Bellekhayırİşletim sistemine tuzak: adresleme hatasıhayırhayırtaban = 300.040limit = 120.900geçerli: 300.040 … 420.939

420.940 = taban + limit: ikinci karşılaştırma başarısız → tuzak. Çekirdek süreci genellikle sonlandırır (Unix'te SIGSEGV).

CPUadres299.999≥ taban ?evet< taban+limit ?Bellekhayırİşletim sistemine tuzak: adresleme hatasıhayırhayırtaban = 300.040limit = 120.900geçerli: 300.040 … 420.939

299.999 tabandan küçük: ilk karşılaştırma başarısız → başka sürecin alanı korunur.

Kullanıcı kipindeki her erişim denetlenir. Çekirdek kipinde denetim yapılmaz; işletim sistemi tüm belleğe erişebilmelidir (Silberschatz Şekil 9.2).

Adres Uzayı

Adres Bağlama Zamanları

Kaynakmain.cNesnemain.oÇalıştırılabilira.outBellektekisüreçderleyicibağlayıcıyükleyici+ diğer .o, statik .a+ dinamik .so (ld.so)MMUher erişimdederleme zamanıyükleme zamanıyürütme zamanı
Bağlama zamanıÜretilen kodKonum değişirseDonanım
DerlemeMutlak kod (ör. MS-DOS .COM)yeniden derlegerekmez
YüklemeYeri değiştirilebilir kod; yükleyici adresleri düzeltiryeniden yüklegerekmez
YürütmeMantıksal adresler; süreç çalışırken taşınabilirhiçbir şeyMMU (taban-limit, sayfalama)

Kaynakta adresler semboliktir (count); derleyici onları göreli adrese (“modül başından 14 bayt”), bağlayıcı/yükleyici mutlak adrese (74014) bağlar. Modern genel amaçlı sistemlerin hepsi yürütme zamanı bağlama kullanır.

Adres Uzayı

Mantıksal ve Fiziksel Adres, MMU

  • Mantıksal (sanal) adres: CPU'nun ürettiği adres. Fiziksel adres: bellek biriminin gördüğü, adres yazmacına (MAR) yüklenen adres.
  • Derleme ve yükleme zamanı bağlamada ikisi aynıdır; yürütme zamanı bağlamada farklıdır.
  • Mantıksal adres uzayı: programın ürettiği adresler kümesi; fiziksel adres uzayı: bunlara karşılık gelen fiziksel adresler.
  • Çalışma anındaki dönüşümü MMU (bellek yönetim birimi) donanımı yapar. Program fiziksel adresleri hiç görmez.
  • Bugünkü işlemcilerde MMU, TLB'leri ve sayfa tablosu yürüyücüsüyle birlikte her çekirdeğin içindedir.
CPU yongasıCPUMMUsanalfiziksel adresveriyoluBellekDisk denetleyici

Adres Uzayı · Adım adım

MMU ile Dinamik Yer Değiştirme

CPUmantıksal346< limit ?3.000limit yazmacıevet+14.000taban (yer değiştirme)fiziksel14.346Bellekhayırtuzak: adresleme hatası

Mantıksal 346 < 3.000 → fiziksel 346 + 14.000 = 14.346. Program 0 ile 2.999 arasını görür.

CPUmantıksal2.999< limit ?3.000limit yazmacıevet+14.000taban (yer değiştirme)fiziksel16.999Bellekhayırtuzak: adresleme hatası

2.999 son geçerli mantıksal adres → 16.999.

CPUmantıksal3.500< limit ?3.000limit yazmacıevet+14.000taban (yer değiştirme)fiziksel—Bellekhayırtuzak: adresleme hatası

3.500 ≥ limit → toplama yapılmadan tuzak. Karşılaştırma mantıksal adres üzerinden olduğu için taban değeri ne olursa olsun aynıdır.

CPUmantıksal28< limit ?16.384limit yazmacıevet+16.384taban (yer değiştirme)fiziksel16.412Bellekhayırtuzak: adresleme hatası

Önceki örnekteki B programı: taban = limit = 16.384. JMP 28 değişmeden kalır, MMU 28 + 16.384 = 16.412 üretir. Statik yer değiştirmeye gerek kalmaz.

Silberschatz'ın yer değiştirme yazmacı Tanenbaum'un taban yazmacıdır. Her erişimde bir toplama ve bir karşılaştırma gerekir; toplama, elde yayılımı yüzünden özel devre olmadan yavaştır.

Bağlama ve Yükleme · Kodu adım adım çalıştır

Dinamik Yükleme

#include <dlfcn.h>
#include <stdio.h>

int main(void) {
  void *h = dlopen("libm.so.6", RTLD_LAZY);
  if (!h) { puts(dlerror()); return 1; }
  double (*kok)(double) =
      (double (*)(double)) dlsym(h, "sqrt");
  printf("%.3f\n", kok(2.0));
  dlclose(h);
  return 0;
}
mainyığıtlibcyığınsürecin adres uzayı0yüksek

Program başladı: adres uzayında yalnız main, libc, yığıt (heap) ve yığın (stack) var; libm yüklü değil.

mainyığıtlibmlibcyığınsürecin adres uzayı0yüksek

dlopen: dinamik bağlayıcı (ld.so) dosyayı bulur, mmap ile adres uzayına eşler. Yükleme şimdi, programın isteğiyle olur.

mainyığıtlibmlibcyığınsürecin adres uzayı0yüksek

dlsym sembol tablosunda sqrt'u arar ve o sürecin adres uzayındaki adresini döndürür.

mainyığıtlibmlibcyığınsürecin adres uzayı0yüksek

İşlev işaretçisiyle çağrı yapılır; çıktı 1.414.

mainyığıtlibcyığınsürecin adres uzayı0yüksek

dlclose: başvuru sayısı 0'a inince kütüphane adres uzayından çıkarılır.

Rutin çağrılana kadar belleğe alınmaz; kullanılmayan kod hiç yüklenmez. Donanım desteği gerekmez, program böyle tasarlanır; işletim sistemi kütüphane sağlar (dlopen, Windows'ta LoadLibrary/GetProcAddress). glibc 2.34'ten beri -ldl gerekmez.

Bağlama ve Yükleme

Statik ve Dinamik Bağlama

Statik bağlamaDinamik bağlama
Kim, ne zaman?Bağlayıcı (ld), derlemeden sonraDinamik bağlayıcı (ld.so), yüklemede/çalışırken
Dosya.a, .lib.so, .dll, .dylib
BellekHer programda ayrı kopyaKod sayfaları bir kez bellekte, paylaşılır
GüncellemeYeniden bağlamak gerekirKütüphaneyi değiştirmek yeter (sürüm: soname)
RiskBüyük dosya, güvenlik yaması gecikirSürüm uyuşmazlığı (“DLL cehennemi”)
  • Statik: kütüphane rutinleri ikili dosyaya kopyalanır (ld *.o -lc -lm).
  • Dinamik: dosyada yalnızca bir taslak (stub) kalır; adres yürütme zamanında çözülür.
Süreç 1kodverilibc.soyığınSüreç 2kodverilibc.soyığınlibc kodutek kopyafiziksel bellek

Bağlama ve Yükleme · Adım adım

Tembel Bağlama: PLT ve GOT

maincall printf@pltPLT girdisijmp *GOT[printf]GOT[printf]→ çözücüld.so çözücü_dl_runtime_resolvelibc: printfgerçek kod1. çağrı

Derleyici printf'in adresini bilmez; çağrı küçük bir PLT (procedure linkage table) taslağına gider. Pptx'teki stub budur.

maincall printf@pltPLT girdisijmp *GOT[printf]GOT[printf]→ çözücüld.so çözücü_dl_runtime_resolvelibc: printfgerçek kod1. çağrı

PLT, GOT (global offset table) içindeki adrese dolaylı atlar. Başlangıçta GOT girdisi çözücüyü gösterir.

maincall printf@pltPLT girdisijmp *GOT[printf]GOT[printf]→ çözücüld.so çözücü_dl_runtime_resolvelibc: printfgerçek kodadresi yaz1. çağrı

ld.so çözücüsü sembolü yüklü kütüphanelerde arar, bulduğu adresi GOT'a yazar.

maincall printf@pltPLT girdisijmp *GOT[printf]GOT[printf]→ printfld.so çözücü_dl_runtime_resolvelibc: printfgerçek kod1. çağrı

Çözücü printf'e atlar. Kod sayfaları değişmedi; yalnızca sürece özel GOT sayfası değişti, bu yüzden kod paylaşılabilir kalır.

maincall printf@pltPLT girdisijmp *GOT[printf]GOT[printf]→ printfld.so çözücü_dl_runtime_resolvelibc: printfgerçek kod2. ve sonraki çağrılar

Sonraki çağrılar PLT → GOT → printf: yalnızca bir dolaylı atlama. Güvenlik için birçok dağıtım -z now (tam RELRO) ile tüm sembolleri yüklemede çözüp GOT'u salt okunur yapar.

Kitaplardaki “taslak kendini rutinin adresiyle değiştirir” anlatımı kavramsaldır; ELF sistemlerinde değişen kod değil, GOT girdisidir. Bunu işletim sistemi değil kullanıcı alanındaki dinamik bağlayıcı yapar.

Bağlama ve Yükleme

Kütüphane Oluşturma: Statik ve Paylaşımlı

Statik kütüphane

$ gcc -c func.c -o func.o
$ ar rcs libfunc.a func.o
$ gcc main.c -o main -static -L. -lfunc
$ ./main
  • ar nesne dosyalarını arşivler; bağlayıcı yalnızca gereken nesneleri kopyalar.
  • -static libc'nin de statik sürümünü (libc.a) ister.

Paylaşımlı kütüphane

$ gcc -fPIC -c func.c -o func.o
$ gcc -shared -o libfunc.so func.o
$ gcc main.c -o main -L. -lfunc
$ export LD_LIBRARY_PATH=$(pwd)
$ ./main
$ ldd ./main   (libfunc.so => ./libfunc.so)
  • -fPIC: konumdan bağımsız kod; mutlak adres yerine PC'ye göreli adresleme, veriye GOT üzerinden erişim.
  • Böylece aynı fiziksel sayfa her süreçte farklı sanal adrese eşlenebilir (ASLR).
  • LD_LIBRARY_PATH yerine kalıcı çözüm: -Wl,-rpath,'$ORIGIN' ya da ldconfig.

Modern dağıtımlar programları da konumdan bağımsız (PIE) derler; böylece programın kendisi de ASLR ile rastgele adrese yüklenir.

Takas

Takas (Swapping)

  • Standart takas: bir sürecin tamamı geçici olarak yedekleme deposuna (disk) yazılır, sonra geri getirilir.
  • Toplam bellek ihtiyacı fiziksel belleği aşabilir; çoklu programlama derecesi artar.
  • Geri gelen süreç başka adrese yerleşebilir → yürütme zamanı bağlama gerekir.
  • Bedel: 100 MB süreç, 50 MB/s disk → 2 s dışarı + 2 s içeri = 4 s (Silberschatz).
  • Bekleyen G/Ç'si olan süreç takas edilmez (DMA eski adrese yazar) ya da G/Ç çekirdek tamponlarından yapılır.
İşletim sistemikullanıcı alanıP1(P2 için yer)ana bellekP1P2yedekleme deposu① dışarı② içeri

Takas

Sayfa Takası ve Modern Sistemler

  • Bütün süreci taşımak bugün kabul edilemez: 1 GiB süreç, 3 GB/s NVMe → gidiş-dönüş ≈ 0,72 s.
  • Linux, Windows, macOS sayfa takas eder: yalnızca uzun süredir kullanılmayan (soğuk) sayfalar dışarı gider, 4 KiB'lık bir sayfa onlarca µs'de gelir.
  • Diske gitmeden önce sıkıştırma: Linux zswap ve zram, Windows bellek sıkıştırma, macOS sıkıştırıcı.
  • Mobil: flaş ömrü ve enerji yüzünden geleneksel takas yok ya da sınırlı; Android zram + lmkd, iOS sıkıştırma + uygulama sonlandırma (jetsam).
  • Sayfa düzeyinde takas ve sayfa değiştirme algoritmaları Bölüm 9'un konusudur.
ana bellekP1 s0P2 s3P1 s2P3 s1takas alanıP1 s1P1 s4P2 s0P3 s0P2 s1sayfa dışarısayfa içeri
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.